Improve output: distinguish between failed assertions (failures) and unexpected exceptions (errors), and print a filtered stack trace for any exception.
This commit is contained in:
commit
4f2e303079
1839 changed files with 235630 additions and 0 deletions
395
webapp/web/src/widget/Editor2.js
Normal file
395
webapp/web/src/widget/Editor2.js
Normal file
|
@ -0,0 +1,395 @@
|
|||
/*
|
||||
Copyright (c) 2004-2006, The Dojo Foundation
|
||||
All Rights Reserved.
|
||||
|
||||
Licensed under the Academic Free License version 2.1 or above OR the
|
||||
modified BSD license. For more information on Dojo licensing, see:
|
||||
|
||||
http://dojotoolkit.org/community/licensing.shtml
|
||||
*/
|
||||
|
||||
/* TODO:
|
||||
* - font selector
|
||||
* - test, bug fix, more features :)
|
||||
*/
|
||||
dojo.provide("dojo.widget.Editor2");
|
||||
dojo.provide("dojo.widget.html.Editor2");
|
||||
dojo.require("dojo.io.*");
|
||||
dojo.require("dojo.widget.*");
|
||||
dojo.require("dojo.widget.RichText");
|
||||
dojo.require("dojo.widget.Editor2Toolbar");
|
||||
// dojo.require("dojo.widget.ColorPalette");
|
||||
// dojo.require("dojo.string.extras");
|
||||
|
||||
dojo.widget.defineWidget(
|
||||
"dojo.widget.html.Editor2",
|
||||
dojo.widget.html.RichText,
|
||||
{
|
||||
saveUrl: "",
|
||||
saveMethod: "post",
|
||||
saveArgName: "editorContent",
|
||||
closeOnSave: false,
|
||||
shareToolbar: false,
|
||||
toolbarAlwaysVisible: false,
|
||||
htmlEditing: false,
|
||||
_inHtmlMode: false,
|
||||
_htmlEditNode: null,
|
||||
|
||||
commandList: dojo.widget.html.Editor2Toolbar.prototype.commandList,
|
||||
toolbarWidget: null,
|
||||
scrollInterval: null,
|
||||
|
||||
|
||||
editorOnLoad: function(){
|
||||
var toolbars = dojo.widget.byType("Editor2Toolbar");
|
||||
if((!toolbars.length)||(!this.shareToolbar)){
|
||||
var tbOpts = {};
|
||||
tbOpts.templatePath = dojo.uri.dojoUri("src/widget/templates/HtmlEditorToolbarOneline.html");
|
||||
this.toolbarWidget = dojo.widget.createWidget("Editor2Toolbar",
|
||||
tbOpts, this.domNode, "before");
|
||||
dojo.event.connect(this, "destroy", this.toolbarWidget, "destroy");
|
||||
this.toolbarWidget.hideUnusableButtons(this);
|
||||
|
||||
if(this.object){
|
||||
this.tbBgIframe = new dojo.html.BackgroundIframe(this.toolbarWidget.domNode);
|
||||
this.tbBgIframe.iframe.style.height = "30px";
|
||||
}
|
||||
|
||||
// need to set position fixed to wherever this thing has landed
|
||||
if(this.toolbarAlwaysVisible){
|
||||
var src = document["documentElement"]||window;
|
||||
this.scrollInterval = setInterval(dojo.lang.hitch(this, "globalOnScrollHandler"), 100);
|
||||
// dojo.event.connect(src, "onscroll", this, "globalOnScrollHandler");
|
||||
dojo.event.connect("before", this, "destroyRendering", this, "unhookScroller");
|
||||
}
|
||||
}else{
|
||||
// FIXME: should we try harder to explicitly manage focus in
|
||||
// order to prevent too many editors from all querying
|
||||
// for button status concurrently?
|
||||
// FIXME: selecting in one shared toolbar doesn't clobber
|
||||
// selection in the others. This is problematic.
|
||||
this.toolbarWidget = toolbars[0];
|
||||
}
|
||||
dojo.event.topic.registerPublisher("Editor2.clobberFocus", this.editNode, "onfocus");
|
||||
// dojo.event.topic.registerPublisher("Editor2.clobberFocus", this.editNode, "onclick");
|
||||
dojo.event.topic.subscribe("Editor2.clobberFocus", this, "setBlur");
|
||||
dojo.event.connect(this.editNode, "onfocus", this, "setFocus");
|
||||
dojo.event.connect(this.toolbarWidget.linkButton, "onclick",
|
||||
dojo.lang.hitch(this, function(){
|
||||
var range;
|
||||
if(this.document.selection){
|
||||
range = this.document.selection.createRange().text;
|
||||
}else if(dojo.render.html.mozilla){
|
||||
range = this.window.getSelection().toString();
|
||||
}
|
||||
if(range.length){
|
||||
this.toolbarWidget.exec("createlink",
|
||||
prompt("Please enter the URL of the link:", "http://"));
|
||||
}else{
|
||||
alert("Please select text to link");
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
var focusFunc = dojo.lang.hitch(this, function(){
|
||||
if(dojo.render.html.ie){
|
||||
this.editNode.focus();
|
||||
}else{
|
||||
this.window.focus();
|
||||
}
|
||||
});
|
||||
|
||||
dojo.event.connect(this.toolbarWidget, "formatSelectClick", focusFunc);
|
||||
dojo.event.connect(this, "execCommand", focusFunc);
|
||||
|
||||
if(this.htmlEditing){
|
||||
var tb = this.toolbarWidget.htmltoggleButton;
|
||||
if(tb){
|
||||
tb.style.display = "";
|
||||
dojo.event.connect(this.toolbarWidget, "htmltoggleClick",
|
||||
this, "toggleHtmlEditing");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
toggleHtmlEditing: function(){
|
||||
if(!this._inHtmlMode){
|
||||
this._inHtmlMode = true;
|
||||
this.toolbarWidget.highlightButton("htmltoggle");
|
||||
if(!this._htmlEditNode){
|
||||
this._htmlEditNode = document.createElement("textarea");
|
||||
dojo.html.insertBefore(this._htmlEditNode, this.domNode);
|
||||
}
|
||||
this._htmlEditNode.style.display = "";
|
||||
this._htmlEditNode.style.width = "100%";
|
||||
this._htmlEditNode.style.height = dojo.style.getInnerHeight(this.editNode)+"px";
|
||||
this._htmlEditNode.value = this.editNode.innerHTML;
|
||||
this.domNode.style.display = "none";
|
||||
}else{
|
||||
this._inHtmlMode = false;
|
||||
this.domNode.style.display = "";
|
||||
this.toolbarWidget.unhighlightButton("htmltoggle");
|
||||
dojo.lang.setTimeout(this, "replaceEditorContent", 1, this._htmlEditNode.value);
|
||||
this._htmlEditNode.style.display = "none";
|
||||
this.editNode.focus();
|
||||
}
|
||||
},
|
||||
|
||||
setFocus: function(){
|
||||
// dojo.debug("setFocus:", this);
|
||||
dojo.event.connect(this.toolbarWidget, "exec", this, "execCommand");
|
||||
},
|
||||
|
||||
setBlur: function(){
|
||||
// dojo.debug("setBlur:", this);
|
||||
dojo.event.disconnect(this.toolbarWidget, "exec", this, "execCommand");
|
||||
},
|
||||
|
||||
_scrollSetUp: false,
|
||||
_fixEnabled: false,
|
||||
_scrollThreshold: false,
|
||||
_handleScroll: true,
|
||||
globalOnScrollHandler: function(){
|
||||
var isIE = dojo.render.html.ie;
|
||||
if(!this._handleScroll){ return; }
|
||||
var ds = dojo.style;
|
||||
var tdn = this.toolbarWidget.domNode;
|
||||
var db = document["body"];
|
||||
var totalHeight = ds.getOuterHeight(tdn);
|
||||
if(!this._scrollSetUp){
|
||||
this._scrollSetUp = true;
|
||||
var editorWidth = ds.getOuterWidth(this.domNode);
|
||||
this._scrollThreshold = ds.abs(tdn, false).y;
|
||||
// dojo.debug("threshold:", this._scrollThreshold);
|
||||
if((isIE)&&(db)&&(ds.getStyle(db, "background-image")=="none")){
|
||||
with(db.style){
|
||||
backgroundImage = "url(" + dojo.uri.dojoUri("src/widget/templates/images/blank.gif") + ")";
|
||||
backgroundAttachment = "fixed";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scrollPos = (window["pageYOffset"]) ? window["pageYOffset"] : (document["documentElement"]||document["body"]).scrollTop;
|
||||
|
||||
// FIXME: need to have top and bottom thresholds so toolbar doesn't keep scrolling past the bottom
|
||||
if(scrollPos > this._scrollThreshold){
|
||||
// dojo.debug(scrollPos);
|
||||
if(!this._fixEnabled){
|
||||
this.domNode.style.marginTop = totalHeight+"px";
|
||||
if(isIE){
|
||||
// FIXME: should we just use setBehvior() here instead?
|
||||
var cl = dojo.style.abs(tdn).x;
|
||||
document.body.appendChild(tdn);
|
||||
tdn.style.left = cl+dojo.style.getPixelValue(document.body, "margin-left")+"px";
|
||||
dojo.html.addClass(tdn, "IEFixedToolbar");
|
||||
if(this.object){
|
||||
dojo.html.addClass(this.tbBgIframe, "IEFixedToolbar");
|
||||
}
|
||||
|
||||
}else{
|
||||
with(tdn.style){
|
||||
position = "fixed";
|
||||
top = "0px";
|
||||
}
|
||||
}
|
||||
tdn.style.zIndex = 1000;
|
||||
this._fixEnabled = true;
|
||||
}
|
||||
// if we're showing the floating toolbar, make sure that if
|
||||
// we've scrolled past the bottom of the editor that we hide
|
||||
// the toolbar for this instance of the editor.
|
||||
|
||||
// TODO: when we get multiple editor toolbar support working
|
||||
// correctly, ensure that we check this against the scroll
|
||||
// position of the bottom-most editor instance.
|
||||
if(!dojo.render.html.safari){
|
||||
// safari reports a bunch of things incorrectly here
|
||||
var eHeight = (this.height) ? parseInt(this.height) : ((this.object) ? dojo.style.getInnerHeight(this.editNode) : this._lastHeight);
|
||||
if(scrollPos > (this._scrollThreshold+eHeight)){
|
||||
tdn.style.display = "none";
|
||||
}else{
|
||||
tdn.style.display = "";
|
||||
}
|
||||
}
|
||||
|
||||
}else if(this._fixEnabled){
|
||||
this.domNode.style.marginTop = null;
|
||||
with(tdn.style){
|
||||
position = "";
|
||||
top = "";
|
||||
zIndex = "";
|
||||
if(isIE){
|
||||
marginTop = "";
|
||||
}
|
||||
}
|
||||
if(isIE){
|
||||
dojo.html.removeClass(tdn, "IEFixedToolbar");
|
||||
dojo.html.insertBefore(tdn, this._htmlEditNode||this.domNode);
|
||||
}
|
||||
this._fixEnabled = false;
|
||||
}
|
||||
},
|
||||
|
||||
unhookScroller: function(){
|
||||
this._handleScroll = false;
|
||||
clearInterval(this.scrollInterval);
|
||||
// var src = document["documentElement"]||window;
|
||||
// dojo.event.disconnect(src, "onscroll", this, "globalOnScrollHandler");
|
||||
if(dojo.render.html.ie){
|
||||
dojo.html.removeClass(this.toolbarWidget.domNode, "IEFixedToolbar");
|
||||
}
|
||||
},
|
||||
|
||||
_updateToolbarLastRan: null,
|
||||
_updateToolbarTimer: null,
|
||||
_updateToolbarFrequency: 500,
|
||||
|
||||
updateToolbar: function(force){
|
||||
if((!this.isLoaded)||(!this.toolbarWidget)){ return; }
|
||||
|
||||
// keeps the toolbar from updating too frequently
|
||||
// TODO: generalize this functionality?
|
||||
var diff = new Date() - this._updateToolbarLastRan;
|
||||
if( (!force)&&(this._updateToolbarLastRan)&&
|
||||
((diff < this._updateToolbarFrequency)) ){
|
||||
|
||||
clearTimeout(this._updateToolbarTimer);
|
||||
var _this = this;
|
||||
this._updateToolbarTimer = setTimeout(function() {
|
||||
_this.updateToolbar();
|
||||
}, this._updateToolbarFrequency/2);
|
||||
return;
|
||||
|
||||
}else{
|
||||
this._updateToolbarLastRan = new Date();
|
||||
}
|
||||
// end frequency checker
|
||||
|
||||
dojo.lang.forEach(this.commandList, function(cmd){
|
||||
if(cmd == "inserthtml"){ return; }
|
||||
try{
|
||||
if(this.queryCommandEnabled(cmd)){
|
||||
if(this.queryCommandState(cmd)){
|
||||
this.toolbarWidget.highlightButton(cmd);
|
||||
}else{
|
||||
this.toolbarWidget.unhighlightButton(cmd);
|
||||
}
|
||||
}
|
||||
}catch(e){
|
||||
// alert(cmd+":"+e);
|
||||
}
|
||||
}, this);
|
||||
|
||||
var h = dojo.render.html;
|
||||
|
||||
// safari f's us for selection primitives
|
||||
if(h.safari){ return; }
|
||||
|
||||
var selectedNode = (h.ie) ? this.document.selection.createRange().parentElement() : this.window.getSelection().anchorNode;
|
||||
// make sure we actuall have an element
|
||||
while((selectedNode)&&(selectedNode.nodeType != 1)){
|
||||
selectedNode = selectedNode.parentNode;
|
||||
}
|
||||
if(!selectedNode){ return; }
|
||||
|
||||
var formats = ["p", "pre", "h1", "h2", "h3", "h4"];
|
||||
// gotta run some specialized updates for the various
|
||||
// formatting options
|
||||
var type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())];
|
||||
while((selectedNode)&&(selectedNode!=this.editNode)&&(!type)){
|
||||
selectedNode = selectedNode.parentNode;
|
||||
type = formats[dojo.lang.find(formats, selectedNode.nodeName.toLowerCase())];
|
||||
}
|
||||
if(!type){
|
||||
type = "";
|
||||
}else{
|
||||
if(type.charAt(0)=="h"){
|
||||
this.toolbarWidget.unhighlightButton("bold");
|
||||
}
|
||||
}
|
||||
this.toolbarWidget.selectFormat(type);
|
||||
},
|
||||
|
||||
updateItem: function(item) {
|
||||
try {
|
||||
var cmd = item._name;
|
||||
var enabled = this._richText.queryCommandEnabled(cmd);
|
||||
item.setEnabled(enabled, false, true);
|
||||
|
||||
var active = this._richText.queryCommandState(cmd);
|
||||
if(active && cmd == "underline") {
|
||||
// don't activate underlining if we are on a link
|
||||
active = !this._richText.queryCommandEnabled("unlink");
|
||||
}
|
||||
item.setSelected(active, false, true);
|
||||
return true;
|
||||
} catch(err) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
_save: function(e){
|
||||
// FIXME: how should this behave when there's a larger form in play?
|
||||
if(!this.isClosed){
|
||||
if(this.saveUrl.length){
|
||||
var content = {};
|
||||
content[this.saveArgName] = this.getHtml();
|
||||
dojo.io.bind({
|
||||
method: this.saveMethod,
|
||||
url: this.saveUrl,
|
||||
content: content
|
||||
});
|
||||
}else{
|
||||
dojo.debug("please set a saveUrl for the editor");
|
||||
}
|
||||
if(this.closeOnSave){
|
||||
this.close(e.getName().toLowerCase() == "save");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
wireUpOnLoad: function(){
|
||||
if(!dojo.render.html.ie){
|
||||
/*
|
||||
dojo.event.kwConnect({
|
||||
srcObj: this.document,
|
||||
srcFunc: "click",
|
||||
targetObj: this.toolbarWidget,
|
||||
targetFunc: "hideAllDropDowns",
|
||||
once: true
|
||||
});
|
||||
*/
|
||||
}
|
||||
}
|
||||
},
|
||||
"html",
|
||||
function(){
|
||||
var cp = dojo.widget.html.Editor2.prototype;
|
||||
if(!cp._wrappersSet){
|
||||
cp._wrappersSet = true;
|
||||
cp.fillInTemplate = (function(fit){
|
||||
return function(){
|
||||
fit.call(this);
|
||||
this.editorOnLoad();
|
||||
};
|
||||
})(cp.fillInTemplate);
|
||||
|
||||
cp.onDisplayChanged = (function(odc){
|
||||
return function(){
|
||||
try{
|
||||
odc.call(this);
|
||||
this.updateToolbar();
|
||||
}catch(e){}
|
||||
};
|
||||
})(cp.onDisplayChanged);
|
||||
|
||||
cp.onLoad = (function(ol){
|
||||
return function(){
|
||||
ol.call(this);
|
||||
this.wireUpOnLoad();
|
||||
};
|
||||
})(cp.onLoad);
|
||||
}
|
||||
}
|
||||
);
|
Loading…
Add table
Add a link
Reference in a new issue