Getting ready to upgrade Dojo to 1.1
This commit is contained in:
@@ -1,261 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.ColorPalette"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.ColorPalette"] = true;
|
||||
dojo.provide("dijit.ColorPalette");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
dojo.require("dojo.colors");
|
||||
dojo.require("dojo.i18n");
|
||||
dojo.requireLocalization("dojo", "colors", null, "ko,zh,ja,zh-tw,ru,it,hu,ROOT,fr,pt,pl,es,de,cs");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.ColorPalette",
|
||||
[dijit._Widget, dijit._Templated],
|
||||
{
|
||||
// summary
|
||||
// Grid showing various colors, so the user can pick a certain color
|
||||
|
||||
// defaultTimeout: Number
|
||||
// number of milliseconds before a held key or button becomes typematic
|
||||
defaultTimeout: 500,
|
||||
|
||||
// timeoutChangeRate: Number
|
||||
// fraction of time used to change the typematic timer between events
|
||||
// 1.0 means that each typematic event fires at defaultTimeout intervals
|
||||
// < 1.0 means that each typematic event fires at an increasing faster rate
|
||||
timeoutChangeRate: 0.90,
|
||||
|
||||
// palette: String
|
||||
// Size of grid, either "7x10" or "3x4".
|
||||
palette: "7x10",
|
||||
|
||||
//_value: String
|
||||
// The value of the selected color.
|
||||
value: null,
|
||||
|
||||
//_currentFocus: Integer
|
||||
// Index of the currently focused color.
|
||||
_currentFocus: 0,
|
||||
|
||||
// _xDim: Integer
|
||||
// This is the number of colors horizontally across.
|
||||
_xDim: null,
|
||||
|
||||
// _yDim: Integer
|
||||
/// This is the number of colors vertically down.
|
||||
_yDim: null,
|
||||
|
||||
// _palettes: Map
|
||||
// This represents the value of the colors.
|
||||
// The first level is a hashmap of the different arrays available
|
||||
// The next two dimensions represent the columns and rows of colors.
|
||||
_palettes: {
|
||||
|
||||
"7x10": [["white", "seashell", "cornsilk", "lemonchiffon","lightyellow", "palegreen", "paleturquoise", "lightcyan", "lavender", "plum"],
|
||||
["lightgray", "pink", "bisque", "moccasin", "khaki", "lightgreen", "lightseagreen", "lightskyblue", "cornflowerblue", "violet"],
|
||||
["silver", "lightcoral", "sandybrown", "orange", "palegoldenrod", "chartreuse", "mediumturquoise", "skyblue", "mediumslateblue","orchid"],
|
||||
["gray", "red", "orangered", "darkorange", "yellow", "limegreen", "darkseagreen", "royalblue", "slateblue", "mediumorchid"],
|
||||
["dimgray", "crimson", "chocolate", "coral", "gold", "forestgreen", "seagreen", "blue", "blueviolet", "darkorchid"],
|
||||
["darkslategray","firebrick","saddlebrown", "sienna", "olive", "green", "darkcyan", "mediumblue","darkslateblue", "darkmagenta" ],
|
||||
["black", "darkred", "maroon", "brown", "darkolivegreen", "darkgreen", "midnightblue", "navy", "indigo", "purple"]],
|
||||
|
||||
"3x4": [["white", "lime", "green", "blue"],
|
||||
["silver", "yellow", "fuchsia", "navy"],
|
||||
["gray", "red", "purple", "black"]]
|
||||
|
||||
},
|
||||
|
||||
// _imagePaths: Map
|
||||
// This is stores the path to the palette images
|
||||
_imagePaths: {
|
||||
"7x10": dojo.moduleUrl("dijit", "templates/colors7x10.png"),
|
||||
"3x4": dojo.moduleUrl("dijit", "templates/colors3x4.png")
|
||||
},
|
||||
|
||||
// _paletteCoords: Map
|
||||
// This is a map that is used to calculate the coordinates of the
|
||||
// images that make up the palette.
|
||||
_paletteCoords: {
|
||||
"leftOffset": 4, "topOffset": 4,
|
||||
"cWidth": 20, "cHeight": 20
|
||||
|
||||
},
|
||||
|
||||
// templatePath: String
|
||||
// Path to the template of this widget.
|
||||
templateString:"<div class=\"dijitInline dijitColorPalette\">\n\t<div class=\"dijitColorPaletteInner\" dojoAttachPoint=\"divNode\" waiRole=\"grid\" tabIndex=\"-1\">\n\t\t<img class=\"dijitColorPaletteUnder\" dojoAttachPoint=\"imageNode\" waiRole=\"presentation\">\n\t</div>\t\n</div>\n",
|
||||
|
||||
// _paletteDims: Object
|
||||
// Size of the supported palettes for alignment purposes.
|
||||
_paletteDims: {
|
||||
"7x10": {"width": "206px", "height": "145px"},
|
||||
"3x4": {"width": "86px", "height": "64px"}
|
||||
},
|
||||
|
||||
|
||||
postCreate: function(){
|
||||
// A name has to be given to the colorMap, this needs to be unique per Palette.
|
||||
dojo.mixin(this.divNode.style, this._paletteDims[this.palette]);
|
||||
this.imageNode.setAttribute("src", this._imagePaths[this.palette]);
|
||||
var choices = this._palettes[this.palette];
|
||||
this.domNode.style.position = "relative";
|
||||
this._highlightNodes = [];
|
||||
this.colorNames = dojo.i18n.getLocalization("dojo", "colors", this.lang);
|
||||
|
||||
for(var row=0; row < choices.length; row++){
|
||||
for(var col=0; col < choices[row].length; col++){
|
||||
var highlightNode = document.createElement("img");
|
||||
highlightNode.src = dojo.moduleUrl("dijit", "templates/blank.gif");
|
||||
dojo.addClass(highlightNode, "dijitPaletteImg");
|
||||
var color = choices[row][col];
|
||||
var colorValue = new dojo.Color(dojo.Color.named[color]);
|
||||
highlightNode.alt = this.colorNames[color];
|
||||
highlightNode.color = colorValue.toHex();
|
||||
var highlightStyle = highlightNode.style;
|
||||
highlightStyle.color = highlightStyle.backgroundColor = highlightNode.color;
|
||||
dojo.forEach(["Dijitclick", "MouseOut", "MouseOver", "Blur", "Focus"], function(handler){
|
||||
this.connect(highlightNode, "on"+handler.toLowerCase(), "_onColor"+handler);
|
||||
}, this);
|
||||
this.divNode.appendChild(highlightNode);
|
||||
var coords = this._paletteCoords;
|
||||
highlightStyle.top = coords.topOffset + (row * coords.cHeight) + "px";
|
||||
highlightStyle.left = coords.leftOffset + (col * coords.cWidth) + "px";
|
||||
highlightNode.setAttribute("tabIndex","-1");
|
||||
highlightNode.title = this.colorNames[color];
|
||||
dijit.setWaiRole(highlightNode, "gridcell");
|
||||
highlightNode.index = this._highlightNodes.length;
|
||||
this._highlightNodes.push(highlightNode);
|
||||
}
|
||||
}
|
||||
this._highlightNodes[this._currentFocus].tabIndex = 0;
|
||||
this._xDim = choices[0].length;
|
||||
this._yDim = choices.length;
|
||||
|
||||
// Now set all events
|
||||
// The palette itself is navigated to with the tab key on the keyboard
|
||||
// Keyboard navigation within the Palette is with the arrow keys
|
||||
// Spacebar selects the color.
|
||||
// For the up key the index is changed by negative the x dimension.
|
||||
|
||||
var keyIncrementMap = {
|
||||
UP_ARROW: -this._xDim,
|
||||
// The down key the index is increase by the x dimension.
|
||||
DOWN_ARROW: this._xDim,
|
||||
// Right and left move the index by 1.
|
||||
RIGHT_ARROW: 1,
|
||||
LEFT_ARROW: -1
|
||||
};
|
||||
for(var key in keyIncrementMap){
|
||||
dijit.typematic.addKeyListener(this.domNode,
|
||||
{keyCode:dojo.keys[key], ctrlKey:false, altKey:false, shiftKey:false},
|
||||
this,
|
||||
function(){
|
||||
var increment = keyIncrementMap[key];
|
||||
return function(count){ this._navigateByKey(increment, count); };
|
||||
}(),
|
||||
this.timeoutChangeRate, this.defaultTimeout);
|
||||
}
|
||||
},
|
||||
|
||||
focus: function(){
|
||||
// summary:
|
||||
// Focus this ColorPalette.
|
||||
dijit.focus(this._highlightNodes[this._currentFocus]);
|
||||
},
|
||||
|
||||
onChange: function(color){
|
||||
// summary:
|
||||
// Callback when a color is selected.
|
||||
// color: String
|
||||
// Hex value corresponding to color.
|
||||
// console.debug("Color selected is: "+color);
|
||||
},
|
||||
|
||||
_onColorDijitclick: function(/*Event*/ evt){
|
||||
// summary:
|
||||
// Handler for click, enter key & space key. Selects the color.
|
||||
// evt:
|
||||
// The event.
|
||||
var target = evt.currentTarget;
|
||||
if (this._currentFocus != target.index){
|
||||
this._currentFocus = target.index;
|
||||
dijit.focus(target);
|
||||
}
|
||||
this._selectColor(target);
|
||||
dojo.stopEvent(evt);
|
||||
},
|
||||
|
||||
_onColorMouseOut: function(/*Event*/ evt){
|
||||
// summary:
|
||||
// Handler for onMouseOut. Removes highlight.
|
||||
// evt:
|
||||
// The mouse event.
|
||||
dojo.removeClass(evt.currentTarget, "dijitPaletteImgHighlight");
|
||||
},
|
||||
|
||||
_onColorMouseOver: function(/*Event*/ evt){
|
||||
// summary:
|
||||
// Handler for onMouseOver. Highlights the color.
|
||||
// evt:
|
||||
// The mouse event.
|
||||
var target = evt.currentTarget;
|
||||
target.tabIndex = 0;
|
||||
target.focus();
|
||||
},
|
||||
|
||||
_onColorBlur: function(/*Event*/ evt){
|
||||
// summary:
|
||||
// Handler for onBlur. Removes highlight and sets
|
||||
// the first color as the palette's tab point.
|
||||
// evt:
|
||||
// The blur event.
|
||||
dojo.removeClass(evt.currentTarget, "dijitPaletteImgHighlight");
|
||||
evt.currentTarget.tabIndex = -1;
|
||||
this._currentFocus = 0;
|
||||
this._highlightNodes[0].tabIndex = 0;
|
||||
},
|
||||
|
||||
_onColorFocus: function(/*Event*/ evt){
|
||||
// summary:
|
||||
// Handler for onFocus. Highlights the color.
|
||||
// evt:
|
||||
// The focus event.
|
||||
if(this._currentFocus != evt.currentTarget.index){
|
||||
this._highlightNodes[this._currentFocus].tabIndex = -1;
|
||||
}
|
||||
this._currentFocus = evt.currentTarget.index;
|
||||
dojo.addClass(evt.currentTarget, "dijitPaletteImgHighlight");
|
||||
|
||||
},
|
||||
|
||||
_selectColor: function(selectNode){
|
||||
// summary:
|
||||
// This selects a color. It triggers the onChange event
|
||||
// area:
|
||||
// The area node that covers the color being selected.
|
||||
this.onChange(this.value = selectNode.color);
|
||||
},
|
||||
|
||||
_navigateByKey: function(increment, typeCount){
|
||||
// summary:we
|
||||
// This is the callback for typematic.
|
||||
// It changes the focus and the highlighed color.
|
||||
// increment:
|
||||
// How much the key is navigated.
|
||||
// typeCount:
|
||||
// How many times typematic has fired.
|
||||
|
||||
// typecount == -1 means the key is released.
|
||||
if(typeCount == -1){ return; }
|
||||
|
||||
var newFocusIndex = this._currentFocus + increment;
|
||||
if(newFocusIndex < this._highlightNodes.length && newFocusIndex > -1)
|
||||
{
|
||||
var focusNode = this._highlightNodes[newFocusIndex];
|
||||
focusNode.tabIndex = 0;
|
||||
focusNode.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.Declaration"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.Declaration"] = true;
|
||||
dojo.provide("dijit.Declaration");
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.Declaration",
|
||||
dijit._Widget,
|
||||
{
|
||||
// summary:
|
||||
// The Declaration widget allows a user to declare new widget
|
||||
// classes directly from a snippet of markup.
|
||||
|
||||
_noScript: true,
|
||||
widgetClass: "",
|
||||
replaceVars: true,
|
||||
defaults: null,
|
||||
mixins: [],
|
||||
buildRendering: function(){
|
||||
var src = this.srcNodeRef.parentNode.removeChild(this.srcNodeRef);
|
||||
var preambles = dojo.query("> script[type='dojo/method'][event='preamble']", src).orphan();
|
||||
var scripts = dojo.query("> script[type^='dojo/']", src).orphan();
|
||||
var srcType = src.nodeName;
|
||||
|
||||
var propList = this.defaults||{};
|
||||
|
||||
// map array of strings like [ "dijit.form.Button" ] to array of mixin objects
|
||||
// (note that dojo.map(this.mixins, dojo.getObject) doesn't work because it passes
|
||||
// a bogus third argument to getObject(), confusing it)
|
||||
this.mixins = this.mixins.length ?
|
||||
dojo.map(this.mixins, function(name){ return dojo.getObject(name); } ) :
|
||||
[ dijit._Widget, dijit._Templated ];
|
||||
|
||||
if(preambles.length){
|
||||
// we only support one preamble. So be it.
|
||||
propList.preamble = dojo.parser._functionFromScript(preambles[0]);
|
||||
}
|
||||
propList.widgetsInTemplate = true;
|
||||
propList._skipNodeCache = true;
|
||||
propList.templateString = "<"+srcType+" class='"+src.className+"' dojoAttachPoint='"+(src.getAttribute("dojoAttachPoint")||'')+"' dojoAttachEvent='"+(src.getAttribute("dojoAttachEvent")||'')+"' >"+src.innerHTML.replace(/\%7B/g,"{").replace(/\%7D/g,"}")+"</"+srcType+">";
|
||||
// console.debug(propList.templateString);
|
||||
|
||||
// strip things so we don't create stuff under us in the initial setup phase
|
||||
dojo.query("[dojoType]", src).forEach(function(node){
|
||||
node.removeAttribute("dojoType");
|
||||
});
|
||||
|
||||
// create the new widget class
|
||||
dojo.declare(
|
||||
this.widgetClass,
|
||||
this.mixins,
|
||||
propList
|
||||
);
|
||||
|
||||
// do the connects for each <script type="dojo/connect" event="foo"> block and make
|
||||
// all <script type="dojo/method"> tags execute right after construction
|
||||
var wcp = dojo.getObject(this.widgetClass).prototype;
|
||||
scripts.forEach(function(s){
|
||||
var event = s.getAttribute("event");
|
||||
dojo.connect(wcp, event || "postscript", null, dojo.parser._functionFromScript(s));
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.Dialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.Dialog"] = true;
|
||||
dojo.provide("dijit.Dialog");
|
||||
|
||||
dojo.require("dojo.dnd.move");
|
||||
dojo.require("dojo.fx");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
dojo.require("dijit.layout.ContentPane");
|
||||
dojo.require("dijit.form.Form");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.DialogUnderlay",
|
||||
[dijit._Widget, dijit._Templated],
|
||||
{
|
||||
// summary: the thing that grays out the screen behind the dialog
|
||||
|
||||
// Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe.
|
||||
// Inner div has opacity specified in CSS file.
|
||||
templateString: "<div class=dijitDialogUnderlayWrapper id='${id}_underlay'><div class=dijitDialogUnderlay dojoAttachPoint='node'></div></div>",
|
||||
|
||||
postCreate: function(){
|
||||
dojo.body().appendChild(this.domNode);
|
||||
this.bgIframe = new dijit.BackgroundIframe(this.domNode);
|
||||
},
|
||||
|
||||
layout: function(){
|
||||
// summary
|
||||
// Sets the background to the size of the viewport (rather than the size
|
||||
// of the document) since we need to cover the whole browser window, even
|
||||
// if the document is only a few lines long.
|
||||
|
||||
var viewport = dijit.getViewport();
|
||||
var is = this.node.style,
|
||||
os = this.domNode.style;
|
||||
|
||||
os.top = viewport.t + "px";
|
||||
os.left = viewport.l + "px";
|
||||
is.width = viewport.w + "px";
|
||||
is.height = viewport.h + "px";
|
||||
|
||||
// process twice since the scroll bar may have been removed
|
||||
// by the previous resizing
|
||||
var viewport2 = dijit.getViewport();
|
||||
if(viewport.w != viewport2.w){ is.width = viewport2.w + "px"; }
|
||||
if(viewport.h != viewport2.h){ is.height = viewport2.h + "px"; }
|
||||
},
|
||||
|
||||
show: function(){
|
||||
this.domNode.style.display = "block";
|
||||
this.layout();
|
||||
if(this.bgIframe.iframe){
|
||||
this.bgIframe.iframe.style.display = "block";
|
||||
}
|
||||
this._resizeHandler = this.connect(window, "onresize", "layout");
|
||||
},
|
||||
|
||||
hide: function(){
|
||||
this.domNode.style.display = "none";
|
||||
if(this.bgIframe.iframe){
|
||||
this.bgIframe.iframe.style.display = "none";
|
||||
}
|
||||
this.disconnect(this._resizeHandler);
|
||||
},
|
||||
|
||||
uninitialize: function(){
|
||||
if(this.bgIframe){
|
||||
this.bgIframe.destroy();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.Dialog",
|
||||
[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],
|
||||
{
|
||||
// summary:
|
||||
// Pops up a modal dialog window, blocking access to the screen
|
||||
// and also graying out the screen Dialog is extended from
|
||||
// ContentPane so it supports all the same parameters (href, etc.)
|
||||
|
||||
templateString: null,
|
||||
templateString:"<div class=\"dijitDialog\">\n\t<div dojoAttachPoint=\"titleBar\" class=\"dijitDialogTitleBar\" tabindex=\"0\" waiRole=\"dialog\">\n\t<span dojoAttachPoint=\"titleNode\" class=\"dijitDialogTitle\">${title}</span>\n\t<span dojoAttachPoint=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" dojoAttachEvent=\"onclick: hide\">\n\t\t<span dojoAttachPoint=\"closeText\" class=\"closeText\">x</span>\n\t</span>\n\t</div>\n\t\t<div dojoAttachPoint=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n\t<span dojoAttachPoint=\"tabEnd\" dojoAttachEvent=\"onfocus:_cycleFocus\" tabindex=\"0\"></span>\n</div>\n",
|
||||
|
||||
// open: Boolean
|
||||
// is True or False depending on state of dialog
|
||||
open: false,
|
||||
|
||||
// duration: Integer
|
||||
// The time in milliseconds it takes the dialog to fade in and out
|
||||
duration: 400,
|
||||
|
||||
_lastFocusItem:null,
|
||||
|
||||
attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
|
||||
{title: "titleBar"}),
|
||||
|
||||
postCreate: function(){
|
||||
dojo.body().appendChild(this.domNode);
|
||||
this.inherited("postCreate",arguments);
|
||||
this.domNode.style.display="none";
|
||||
this.connect(this, "onExecute", "hide");
|
||||
this.connect(this, "onCancel", "hide");
|
||||
},
|
||||
|
||||
onLoad: function(){
|
||||
// summary:
|
||||
// when href is specified we need to reposition the dialog after the data is loaded
|
||||
this._position();
|
||||
this.inherited("onLoad",arguments);
|
||||
},
|
||||
|
||||
_setup: function(){
|
||||
// summary:
|
||||
// stuff we need to do before showing the Dialog for the first
|
||||
// time (but we defer it until right beforehand, for
|
||||
// performance reasons)
|
||||
|
||||
this._modalconnects = [];
|
||||
|
||||
if(this.titleBar){
|
||||
this._moveable = new dojo.dnd.Moveable(this.domNode, { handle: this.titleBar });
|
||||
}
|
||||
|
||||
this._underlay = new dijit.DialogUnderlay();
|
||||
|
||||
var node = this.domNode;
|
||||
this._fadeIn = dojo.fx.combine(
|
||||
[dojo.fadeIn({
|
||||
node: node,
|
||||
duration: this.duration
|
||||
}),
|
||||
dojo.fadeIn({
|
||||
node: this._underlay.domNode,
|
||||
duration: this.duration,
|
||||
onBegin: dojo.hitch(this._underlay, "show")
|
||||
})
|
||||
]
|
||||
);
|
||||
|
||||
this._fadeOut = dojo.fx.combine(
|
||||
[dojo.fadeOut({
|
||||
node: node,
|
||||
duration: this.duration,
|
||||
onEnd: function(){
|
||||
node.style.display="none";
|
||||
}
|
||||
}),
|
||||
dojo.fadeOut({
|
||||
node: this._underlay.domNode,
|
||||
duration: this.duration,
|
||||
onEnd: dojo.hitch(this._underlay, "hide")
|
||||
})
|
||||
]
|
||||
);
|
||||
},
|
||||
|
||||
uninitialize: function(){
|
||||
if(this._underlay){
|
||||
this._underlay.destroy();
|
||||
}
|
||||
},
|
||||
|
||||
_position: function(){
|
||||
// summary: position modal dialog in center of screen
|
||||
|
||||
if(dojo.hasClass(dojo.body(),"dojoMove")){ return; }
|
||||
var viewport = dijit.getViewport();
|
||||
var mb = dojo.marginBox(this.domNode);
|
||||
|
||||
var style = this.domNode.style;
|
||||
style.left = Math.floor((viewport.l + (viewport.w - mb.w)/2)) + "px";
|
||||
style.top = Math.floor((viewport.t + (viewport.h - mb.h)/2)) + "px";
|
||||
},
|
||||
|
||||
_findLastFocus: function(/*Event*/ evt){
|
||||
// summary: called from onblur of dialog container to determine the last focusable item
|
||||
this._lastFocused = evt.target;
|
||||
},
|
||||
|
||||
_cycleFocus: function(/*Event*/ evt){
|
||||
// summary: when tabEnd receives focus, advance focus around to titleBar
|
||||
|
||||
// on first focus to tabEnd, store the last focused item in dialog
|
||||
if(!this._lastFocusItem){
|
||||
this._lastFocusItem = this._lastFocused;
|
||||
}
|
||||
this.titleBar.focus();
|
||||
},
|
||||
|
||||
_onKey: function(/*Event*/ evt){
|
||||
if(evt.keyCode){
|
||||
var node = evt.target;
|
||||
// see if we are shift-tabbing from titleBar
|
||||
if(node == this.titleBar && evt.shiftKey && evt.keyCode == dojo.keys.TAB){
|
||||
if(this._lastFocusItem){
|
||||
this._lastFocusItem.focus(); // send focus to last item in dialog if known
|
||||
}
|
||||
dojo.stopEvent(evt);
|
||||
}else{
|
||||
// see if the key is for the dialog
|
||||
while(node){
|
||||
if(node == this.domNode){
|
||||
if(evt.keyCode == dojo.keys.ESCAPE){
|
||||
this.hide();
|
||||
}else{
|
||||
return; // just let it go
|
||||
}
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
// this key is for the disabled document window
|
||||
if(evt.keyCode != dojo.keys.TAB){ // allow tabbing into the dialog for a11y
|
||||
dojo.stopEvent(evt);
|
||||
// opera won't tab to a div
|
||||
}else if (!dojo.isOpera){
|
||||
try{
|
||||
this.titleBar.focus();
|
||||
}catch(e){/*squelch*/}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
show: function(){
|
||||
// summary: display the dialog
|
||||
|
||||
// first time we show the dialog, there's some initialization stuff to do
|
||||
if(!this._alreadyInitialized){
|
||||
this._setup();
|
||||
this._alreadyInitialized=true;
|
||||
}
|
||||
|
||||
if(this._fadeOut.status() == "playing"){
|
||||
this._fadeOut.stop();
|
||||
}
|
||||
|
||||
this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout"));
|
||||
this._modalconnects.push(dojo.connect(document.documentElement, "onkeypress", this, "_onKey"));
|
||||
|
||||
// IE doesn't bubble onblur events - use ondeactivate instead
|
||||
var ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";
|
||||
this._modalconnects.push(dojo.connect(this.containerNode, ev, this, "_findLastFocus"));
|
||||
|
||||
dojo.style(this.domNode, "opacity", 0);
|
||||
this.domNode.style.display="block";
|
||||
this.open = true;
|
||||
this._loadCheck(); // lazy load trigger
|
||||
|
||||
this._position();
|
||||
|
||||
this._fadeIn.play();
|
||||
|
||||
this._savedFocus = dijit.getFocus(this);
|
||||
|
||||
// set timeout to allow the browser to render dialog
|
||||
setTimeout(dojo.hitch(this, function(){
|
||||
dijit.focus(this.titleBar);
|
||||
}), 50);
|
||||
},
|
||||
|
||||
hide: function(){
|
||||
// summary
|
||||
// Hide the dialog
|
||||
|
||||
// if we haven't been initialized yet then we aren't showing and we can just return
|
||||
if(!this._alreadyInitialized){
|
||||
return;
|
||||
}
|
||||
|
||||
if(this._fadeIn.status() == "playing"){
|
||||
this._fadeIn.stop();
|
||||
}
|
||||
this._fadeOut.play();
|
||||
|
||||
if (this._scrollConnected){
|
||||
this._scrollConnected = false;
|
||||
}
|
||||
dojo.forEach(this._modalconnects, dojo.disconnect);
|
||||
this._modalconnects = [];
|
||||
|
||||
this.connect(this._fadeOut,"onEnd",dojo.hitch(this,function(){
|
||||
dijit.focus(this._savedFocus);
|
||||
}));
|
||||
this.open = false;
|
||||
},
|
||||
|
||||
layout: function() {
|
||||
// summary: position the Dialog and the underlay
|
||||
if(this.domNode.style.display == "block"){
|
||||
this._underlay.layout();
|
||||
this._position();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.TooltipDialog",
|
||||
[dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin],
|
||||
{
|
||||
// summary:
|
||||
// Pops up a dialog that appears like a Tooltip
|
||||
// title: String
|
||||
// Description of tooltip dialog (required for a11Y)
|
||||
title: "",
|
||||
|
||||
_lastFocusItem: null,
|
||||
|
||||
templateString: null,
|
||||
templateString:"<div class=\"dijitTooltipDialog\" >\n\t<div class=\"dijitTooltipContainer\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" dojoAttachPoint=\"containerNode\" tabindex=\"0\" waiRole=\"dialog\"></div>\n\t</div>\n\t<span dojoAttachPoint=\"tabEnd\" tabindex=\"0\" dojoAttachEvent=\"focus:_cycleFocus\"></span>\n\t<div class=\"dijitTooltipConnector\" ></div>\n</div>\n",
|
||||
|
||||
postCreate: function(){
|
||||
this.inherited("postCreate",arguments);
|
||||
this.connect(this.containerNode, "onkeypress", "_onKey");
|
||||
|
||||
// IE doesn't bubble onblur events - use ondeactivate instead
|
||||
var ev = typeof(document.ondeactivate) == "object" ? "ondeactivate" : "onblur";
|
||||
this.connect(this.containerNode, ev, "_findLastFocus");
|
||||
this.containerNode.title=this.title;
|
||||
},
|
||||
|
||||
orient: function(/*Object*/ corner){
|
||||
// summary: configure widget to be displayed in given position relative to the button
|
||||
this.domNode.className="dijitTooltipDialog " +" dijitTooltipAB"+(corner.charAt(1)=='L'?"Left":"Right")+" dijitTooltip"+(corner.charAt(0)=='T' ? "Below" : "Above");
|
||||
},
|
||||
|
||||
onOpen: function(/*Object*/ pos){
|
||||
// summary: called when dialog is displayed
|
||||
this.orient(pos.corner);
|
||||
this._loadCheck(); // lazy load trigger
|
||||
this.containerNode.focus();
|
||||
},
|
||||
|
||||
_onKey: function(/*Event*/ evt){
|
||||
// summary: keep keyboard focus in dialog; close dialog on escape key
|
||||
if(evt.keyCode == dojo.keys.ESCAPE){
|
||||
this.onCancel();
|
||||
}else if(evt.target == this.containerNode && evt.shiftKey && evt.keyCode == dojo.keys.TAB){
|
||||
if (this._lastFocusItem){
|
||||
this._lastFocusItem.focus();
|
||||
}
|
||||
dojo.stopEvent(evt);
|
||||
}else if(evt.keyCode == dojo.keys.TAB){
|
||||
// we want the browser's default tab handling to move focus
|
||||
// but we don't want the tab to propagate upwards
|
||||
evt.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
_findLastFocus: function(/*Event*/ evt){
|
||||
// summary: called from onblur of dialog container to determine the last focusable item
|
||||
this._lastFocused = evt.target;
|
||||
},
|
||||
|
||||
_cycleFocus: function(/*Event*/ evt){
|
||||
// summary: when tabEnd receives focus, advance focus around to containerNode
|
||||
|
||||
// on first focus to tabEnd, store the last focused item in dialog
|
||||
if(!this._lastFocusItem){
|
||||
this._lastFocusItem = this._lastFocused;
|
||||
}
|
||||
this.containerNode.focus();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.Editor"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.Editor"] = true;
|
||||
dojo.provide("dijit.Editor");
|
||||
dojo.require("dijit._editor.RichText");
|
||||
dojo.require("dijit.Toolbar");
|
||||
dojo.require("dijit._editor._Plugin");
|
||||
dojo.require("dijit._Container");
|
||||
dojo.require("dojo.i18n");
|
||||
dojo.requireLocalization("dijit._editor", "commands", null, "ko,zh,ja,zh-tw,ru,it,hu,fr,pt,pl,es,ROOT,de,cs");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.Editor",
|
||||
dijit._editor.RichText,
|
||||
{
|
||||
// summary: A rich-text Editing widget
|
||||
|
||||
// plugins: Array
|
||||
// a list of plugin names (as strings) or instances (as objects)
|
||||
// for this widget.
|
||||
plugins: null,
|
||||
|
||||
// extraPlugins: Array
|
||||
// a list of extra plugin names which will be appended to plugins array
|
||||
extraPlugins: null,
|
||||
|
||||
constructor: function(){
|
||||
this.plugins=["undo","redo","|","cut","copy","paste","|","bold","italic","underline","strikethrough","|",
|
||||
"insertOrderedList","insertUnorderedList","indent","outdent","|","justifyLeft","justifyRight","justifyCenter","justifyFull"/*"createLink"*/];
|
||||
|
||||
this._plugins=[];
|
||||
this._editInterval = this.editActionInterval * 1000;
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
//for custom undo/redo
|
||||
if(this.customUndo){
|
||||
dojo['require']("dijit._editor.range");
|
||||
this._steps=this._steps.slice(0);
|
||||
this._undoedSteps=this._undoedSteps.slice(0);
|
||||
// this.addKeyHandler('z',this.KEY_CTRL,this.undo);
|
||||
// this.addKeyHandler('y',this.KEY_CTRL,this.redo);
|
||||
}
|
||||
if(dojo.isArray(this.extraPlugins)){
|
||||
this.plugins=this.plugins.concat(this.extraPlugins);
|
||||
}
|
||||
|
||||
// try{
|
||||
dijit.Editor.superclass.postCreate.apply(this, arguments);
|
||||
|
||||
this.commands = dojo.i18n.getLocalization("dijit._editor", "commands", this.lang);
|
||||
|
||||
if(!this.toolbar){
|
||||
// if we haven't been assigned a toolbar, create one
|
||||
var toolbarNode = dojo.doc.createElement("div");
|
||||
dojo.place(toolbarNode, this.editingArea, "before");
|
||||
this.toolbar = new dijit.Toolbar({}, toolbarNode);
|
||||
}
|
||||
|
||||
dojo.forEach(this.plugins, this.addPlugin, this);
|
||||
this.onNormalizedDisplayChanged(); //update toolbar button status
|
||||
// }catch(e){ console.debug(e); }
|
||||
},
|
||||
destroy: function(){
|
||||
dojo.forEach(this._plugins, function(p){
|
||||
if(p.destroy){
|
||||
p.destroy();
|
||||
}
|
||||
});
|
||||
this._plugins=[];
|
||||
this.toolbar.destroy(); delete this.toolbar;
|
||||
this.inherited('destroy',arguments);
|
||||
},
|
||||
addPlugin: function(/*String||Object*/plugin, /*Integer?*/index){
|
||||
// summary:
|
||||
// takes a plugin name as a string or a plugin instance and
|
||||
// adds it to the toolbar and associates it with this editor
|
||||
// instance. The resulting plugin is added to the Editor's
|
||||
// plugins array. If index is passed, it's placed in the plugins
|
||||
// array at that index. No big magic, but a nice helper for
|
||||
// passing in plugin names via markup.
|
||||
// plugin: String, args object or plugin instance. Required.
|
||||
// args: This object will be passed to the plugin constructor.
|
||||
// index:
|
||||
// Integer, optional. Used when creating an instance from
|
||||
// something already in this.plugins. Ensures that the new
|
||||
// instance is assigned to this.plugins at that index.
|
||||
var args=dojo.isString(plugin)?{name:plugin}:plugin;
|
||||
if(!args.setEditor){
|
||||
var o={"args":args,"plugin":null,"editor":this};
|
||||
dojo.publish("dijit.Editor.getPlugin",[o]);
|
||||
if(!o.plugin){
|
||||
var pc = dojo.getObject(args.name);
|
||||
if(pc){
|
||||
o.plugin=new pc(args);
|
||||
}
|
||||
}
|
||||
if(!o.plugin){
|
||||
console.debug('Cannot find plugin',plugin);
|
||||
return;
|
||||
}
|
||||
plugin=o.plugin;
|
||||
}
|
||||
if(arguments.length > 1){
|
||||
this._plugins[index] = plugin;
|
||||
}else{
|
||||
this._plugins.push(plugin);
|
||||
}
|
||||
plugin.setEditor(this);
|
||||
if(dojo.isFunction(plugin.setToolbar)){
|
||||
plugin.setToolbar(this.toolbar);
|
||||
}
|
||||
},
|
||||
/* beginning of custom undo/redo support */
|
||||
|
||||
// customUndo: Boolean
|
||||
// Whether we shall use custom undo/redo support instead of the native
|
||||
// browser support. By default, we only enable customUndo for IE, as it
|
||||
// has broken native undo/redo support. Note: the implementation does
|
||||
// support other browsers which have W3C DOM2 Range API.
|
||||
customUndo: dojo.isIE,
|
||||
|
||||
// editActionInterval: Integer
|
||||
// When using customUndo, not every keystroke will be saved as a step.
|
||||
// Instead typing (including delete) will be grouped together: after
|
||||
// a user stop typing for editActionInterval seconds, a step will be
|
||||
// saved; if a user resume typing within editActionInterval seconds,
|
||||
// the timeout will be restarted. By default, editActionInterval is 3
|
||||
// seconds.
|
||||
editActionInterval: 3,
|
||||
beginEditing: function(cmd){
|
||||
if(!this._inEditing){
|
||||
this._inEditing=true;
|
||||
this._beginEditing(cmd);
|
||||
}
|
||||
if(this.editActionInterval>0){
|
||||
if(this._editTimer){
|
||||
clearTimeout(this._editTimer);
|
||||
}
|
||||
this._editTimer = setTimeout(dojo.hitch(this, this.endEditing), this._editInterval);
|
||||
}
|
||||
},
|
||||
_steps:[],
|
||||
_undoedSteps:[],
|
||||
execCommand: function(cmd){
|
||||
if(this.customUndo && (cmd=='undo' || cmd=='redo')){
|
||||
return this[cmd]();
|
||||
}else{
|
||||
try{
|
||||
if(this.customUndo){
|
||||
this.endEditing();
|
||||
this._beginEditing();
|
||||
}
|
||||
var r = this.inherited('execCommand',arguments);
|
||||
if(this.customUndo){
|
||||
this._endEditing();
|
||||
}
|
||||
return r;
|
||||
}catch(e){
|
||||
if(dojo.isMoz && /copy|cut|paste/.test(cmd)){
|
||||
// Warn user of platform limitation. Cannot programmatically access keyboard. See ticket #4136
|
||||
var sub = dojo.string.substitute,
|
||||
accel = {cut:'X', copy:'C', paste:'V'},
|
||||
isMac = navigator.userAgent.indexOf("Macintosh") != -1;
|
||||
alert(sub(this.commands.systemShortcutFF,
|
||||
[cmd, sub(this.commands[isMac ? 'appleKey' : 'ctrlKey'], [accel[cmd]])]));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
queryCommandEnabled: function(cmd){
|
||||
if(this.customUndo && (cmd=='undo' || cmd=='redo')){
|
||||
return cmd=='undo'?(this._steps.length>1):(this._undoedSteps.length>0);
|
||||
}else{
|
||||
return this.inherited('queryCommandEnabled',arguments);
|
||||
}
|
||||
},
|
||||
_changeToStep: function(from,to){
|
||||
this.setValue(to.text);
|
||||
var b=to.bookmark;
|
||||
if(!b){ return; }
|
||||
if(dojo.isIE){
|
||||
if(dojo.isArray(b)){//IE CONTROL
|
||||
var tmp=[];
|
||||
dojo.forEach(b,function(n){
|
||||
tmp.push(dijit.range.getNode(n,this.editNode));
|
||||
},this);
|
||||
b=tmp;
|
||||
}
|
||||
}else{//w3c range
|
||||
var r=dijit.range.create();
|
||||
r.setStart(dijit.range.getNode(b.startContainer,this.editNode),b.startOffset);
|
||||
r.setEnd(dijit.range.getNode(b.endContainer,this.editNode),b.endOffset);
|
||||
b=r;
|
||||
}
|
||||
dojo.withGlobal(this.window,'moveToBookmark',dijit,[b]);
|
||||
},
|
||||
undo: function(){
|
||||
// console.log('undo');
|
||||
this.endEditing(true);
|
||||
var s=this._steps.pop();
|
||||
if(this._steps.length>0){
|
||||
this.focus();
|
||||
this._changeToStep(s,this._steps[this._steps.length-1]);
|
||||
this._undoedSteps.push(s);
|
||||
this.onDisplayChanged();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
redo: function(){
|
||||
// console.log('redo');
|
||||
this.endEditing(true);
|
||||
var s=this._undoedSteps.pop();
|
||||
if(s && this._steps.length>0){
|
||||
this.focus();
|
||||
this._changeToStep(this._steps[this._steps.length-1],s);
|
||||
this._steps.push(s);
|
||||
this.onDisplayChanged();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
endEditing: function(ignore_caret){
|
||||
if(this._editTimer){
|
||||
clearTimeout(this._editTimer);
|
||||
}
|
||||
if(this._inEditing){
|
||||
this._endEditing(ignore_caret);
|
||||
this._inEditing=false;
|
||||
}
|
||||
},
|
||||
_getBookmark: function(){
|
||||
var b=dojo.withGlobal(this.window,dijit.getBookmark);
|
||||
if(dojo.isIE){
|
||||
if(dojo.isArray(b)){//CONTROL
|
||||
var tmp=[];
|
||||
dojo.forEach(b,function(n){
|
||||
tmp.push(dijit.range.getIndex(n,this.editNode).o);
|
||||
},this);
|
||||
b=tmp;
|
||||
}
|
||||
}else{//w3c range
|
||||
var tmp=dijit.range.getIndex(b.startContainer,this.editNode).o
|
||||
b={startContainer:tmp,
|
||||
startOffset:b.startOffset,
|
||||
endContainer:b.endContainer===b.startContainer?tmp:dijit.range.getIndex(b.endContainer,this.editNode).o,
|
||||
endOffset:b.endOffset};
|
||||
}
|
||||
return b;
|
||||
},
|
||||
_beginEditing: function(cmd){
|
||||
if(this._steps.length===0){
|
||||
this._steps.push({'text':this.savedContent,'bookmark':this._getBookmark()});
|
||||
}
|
||||
},
|
||||
_endEditing: function(ignore_caret){
|
||||
var v=this.getValue(true);
|
||||
|
||||
this._undoedSteps=[];//clear undoed steps
|
||||
this._steps.push({'text':v,'bookmark':this._getBookmark()});
|
||||
},
|
||||
onKeyDown: function(e){
|
||||
if(!this.customUndo){
|
||||
this.inherited('onKeyDown',arguments);
|
||||
return;
|
||||
}
|
||||
var k=e.keyCode,ks=dojo.keys;
|
||||
if(e.ctrlKey){
|
||||
if(k===90||k===122){ //z
|
||||
dojo.stopEvent(e);
|
||||
this.undo();
|
||||
return;
|
||||
}else if(k===89||k===121){ //y
|
||||
dojo.stopEvent(e);
|
||||
this.redo();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.inherited('onKeyDown',arguments);
|
||||
|
||||
switch(k){
|
||||
case ks.ENTER:
|
||||
this.beginEditing();
|
||||
break;
|
||||
case ks.BACKSPACE:
|
||||
case ks.DELETE:
|
||||
this.beginEditing();
|
||||
break;
|
||||
case 88: //x
|
||||
case 86: //v
|
||||
if(e.ctrlKey && !e.altKey && !e.metaKey){
|
||||
this.endEditing();//end current typing step if any
|
||||
if(e.keyCode == 88){
|
||||
this.beginEditing('cut');
|
||||
//use timeout to trigger after the cut is complete
|
||||
setTimeout(dojo.hitch(this, this.endEditing), 1);
|
||||
}else{
|
||||
this.beginEditing('paste');
|
||||
//use timeout to trigger after the paste is complete
|
||||
setTimeout(dojo.hitch(this, this.endEditing), 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
//pass through
|
||||
default:
|
||||
if(!e.ctrlKey && !e.altKey && !e.metaKey && (e.keyCode<dojo.keys.F1 || e.keyCode>dojo.keys.F15)){
|
||||
this.beginEditing();
|
||||
break;
|
||||
}
|
||||
//pass through
|
||||
case ks.ALT:
|
||||
this.endEditing();
|
||||
break;
|
||||
case ks.UP_ARROW:
|
||||
case ks.DOWN_ARROW:
|
||||
case ks.LEFT_ARROW:
|
||||
case ks.RIGHT_ARROW:
|
||||
case ks.HOME:
|
||||
case ks.END:
|
||||
case ks.PAGE_UP:
|
||||
case ks.PAGE_DOWN:
|
||||
this.endEditing(true);
|
||||
break;
|
||||
//maybe ctrl+backspace/delete, so don't endEditing when ctrl is pressed
|
||||
case ks.CTRL:
|
||||
case ks.SHIFT:
|
||||
case ks.TAB:
|
||||
break;
|
||||
}
|
||||
},
|
||||
_onBlur: function(){
|
||||
this.inherited('_onBlur',arguments);
|
||||
this.endEditing(true);
|
||||
},
|
||||
onClick: function(){
|
||||
this.endEditing(true);
|
||||
this.inherited('onClick',arguments);
|
||||
}
|
||||
/* end of custom undo/redo support */
|
||||
}
|
||||
);
|
||||
|
||||
/* the following code is to registered a handler to get default plugins */
|
||||
dojo.subscribe("dijit.Editor.getPlugin",null,function(o){
|
||||
if(o.plugin){ return; }
|
||||
var args=o.args, p;
|
||||
var _p = dijit._editor._Plugin;
|
||||
var name=args.name;
|
||||
switch(name){
|
||||
case "undo": case "redo": case "cut": case "copy": case "paste": case "insertOrderedList":
|
||||
case "insertUnorderedList": case "indent": case "outdent": case "justifyCenter":
|
||||
case "justifyFull": case "justifyLeft": case "justifyRight": case "delete":
|
||||
case "selectAll": case "removeFormat":
|
||||
p = new _p({ command: name });
|
||||
break;
|
||||
|
||||
case "bold": case "italic": case "underline": case "strikethrough":
|
||||
case "subscript": case "superscript":
|
||||
p = new _p({ buttonClass: dijit.form.ToggleButton, command: name });
|
||||
break;
|
||||
case "|":
|
||||
p = new _p({ button: new dijit.ToolbarSeparator() });
|
||||
break;
|
||||
case "createLink":
|
||||
// dojo['require']('dijit._editor.plugins.LinkDialog');
|
||||
p = new dijit._editor.plugins.LinkDialog({ command: name });
|
||||
break;
|
||||
case "foreColor": case "hiliteColor":
|
||||
p = new dijit._editor.plugins.TextColor({ command: name });
|
||||
break;
|
||||
case "fontName": case "fontSize": case "formatBlock":
|
||||
p = new dijit._editor.plugins.FontChoice({ command: name });
|
||||
}
|
||||
// console.log('name',name,p);
|
||||
o.plugin=p;
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,405 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.InlineEditBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.InlineEditBox"] = true;
|
||||
dojo.provide("dijit.InlineEditBox");
|
||||
|
||||
dojo.require("dojo.i18n");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Container");
|
||||
dojo.require("dijit.form.Button");
|
||||
dojo.require("dijit.form.TextBox");
|
||||
|
||||
dojo.requireLocalization("dijit", "common", null, "ko,zh,ja,zh-tw,ru,it,hu,fr,pt,ROOT,pl,es,de,cs");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.InlineEditBox",
|
||||
dijit._Widget,
|
||||
{
|
||||
// summary
|
||||
// Behavior for an existing node (<p>, <div>, <span>, etc.) so that
|
||||
// when you click it, an editor shows up in place of the original
|
||||
// text. Optionally, Save and Cancel button are displayed below the edit widget.
|
||||
// When Save is clicked, the text is pulled from the edit
|
||||
// widget and redisplayed and the edit widget is again hidden.
|
||||
// By default a plain Textarea widget is used as the editor (or for
|
||||
// inline values a TextBox), but you can specify an editor such as
|
||||
// dijit.Editor (for editing HTML) or a Slider (for adjusting a number).
|
||||
// An edit widget must support the following API to be used:
|
||||
// String getDisplayedValue() OR String getValue()
|
||||
// void setDisplayedValue(String) OR void setValue(String)
|
||||
// void focus()
|
||||
|
||||
// editing: Boolean
|
||||
// Is the node currently in edit mode?
|
||||
editing: false,
|
||||
|
||||
// autoSave: Boolean
|
||||
// Changing the value automatically saves it; don't have to push save button
|
||||
// (and save button isn't even displayed)
|
||||
autoSave: true,
|
||||
|
||||
// buttonSave: String
|
||||
// Save button label
|
||||
buttonSave: "",
|
||||
|
||||
// buttonCancel: String
|
||||
// Cancel button label
|
||||
buttonCancel: "",
|
||||
|
||||
// renderAsHtml: Boolean
|
||||
// Set this to true if the specified Editor's value should be interpreted as HTML
|
||||
// rather than plain text (ie, dijit.Editor)
|
||||
renderAsHtml: false,
|
||||
|
||||
// editor: String
|
||||
// Class name for Editor widget
|
||||
editor: "dijit.form.TextBox",
|
||||
|
||||
// editorParams: Object
|
||||
// Set of parameters for editor, like {required: true}
|
||||
editorParams: {},
|
||||
|
||||
onChange: function(value){
|
||||
// summary: User should set this handler to be notified of changes to value
|
||||
},
|
||||
|
||||
// width: String
|
||||
// Width of editor. By default it's width=100% (ie, block mode)
|
||||
width: "100%",
|
||||
|
||||
// value: String
|
||||
// The display value of the widget in read-only mode
|
||||
value: "",
|
||||
|
||||
// noValueIndicator: String
|
||||
// The text that gets displayed when there is no value (so that the user has a place to click to edit)
|
||||
noValueIndicator: "<span style='font-family: wingdings; text-decoration: underline;'> ✍ </span>",
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.inherited('postMixInProperties', arguments);
|
||||
|
||||
// save pointer to original source node, since Widget nulls-out srcNodeRef
|
||||
this.displayNode = this.srcNodeRef;
|
||||
|
||||
// connect handlers to the display node
|
||||
var events = {
|
||||
ondijitclick: "_onClick",
|
||||
onmouseover: "_onMouseOver",
|
||||
onmouseout: "_onMouseOut",
|
||||
onfocus: "_onMouseOver",
|
||||
onblur: "_onMouseOut"
|
||||
};
|
||||
for(var name in events){
|
||||
this.connect(this.displayNode, name, events[name]);
|
||||
}
|
||||
dijit.setWaiRole(this.displayNode, "button");
|
||||
if(!this.displayNode.getAttribute("tabIndex")){
|
||||
this.displayNode.setAttribute("tabIndex", 0);
|
||||
}
|
||||
|
||||
if(!this.value){
|
||||
this.value = this.displayNode.innerHTML;
|
||||
}
|
||||
this._setDisplayValue(this.value); // if blank, change to icon for "input needed"
|
||||
},
|
||||
|
||||
_onMouseOver: function(){
|
||||
dojo.addClass(this.displayNode, this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion");
|
||||
},
|
||||
|
||||
_onMouseOut: function(){
|
||||
dojo.removeClass(this.displayNode, this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion");
|
||||
},
|
||||
|
||||
_onClick: function(/*Event*/ e){
|
||||
if(this.disabled){ return; }
|
||||
if(e){ dojo.stopEvent(e); }
|
||||
this._onMouseOut();
|
||||
|
||||
// Since FF gets upset if you move a node while in an event handler for that node...
|
||||
setTimeout(dojo.hitch(this, "_edit"), 0);
|
||||
},
|
||||
|
||||
_edit: function(){
|
||||
// summary: display the editor widget in place of the original (read only) markup
|
||||
|
||||
this.editing = true;
|
||||
|
||||
var editValue =
|
||||
(this.renderAsHtml ?
|
||||
this.value :
|
||||
this.value.replace(/\s*\r?\n\s*/g,"").replace(/<br\/?>/gi, "\n").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&"));
|
||||
|
||||
// Placeholder for edit widget
|
||||
// Put place holder (and eventually editWidget) before the display node so that it's positioned correctly
|
||||
// when Calendar dropdown appears, which happens automatically on focus.
|
||||
var placeholder = document.createElement("span");
|
||||
dojo.place(placeholder, this.domNode, "before");
|
||||
|
||||
var ew = this.editWidget = new dijit._InlineEditor({
|
||||
value: dojo.trim(editValue),
|
||||
autoSave: this.autoSave,
|
||||
buttonSave: this.buttonSave,
|
||||
buttonCancel: this.buttonCancel,
|
||||
renderAsHtml: this.renderAsHtml,
|
||||
editor: this.editor,
|
||||
editorParams: this.editorParams,
|
||||
style: dojo.getComputedStyle(this.displayNode),
|
||||
save: dojo.hitch(this, "save"),
|
||||
cancel: dojo.hitch(this, "cancel"),
|
||||
width: this.width
|
||||
}, placeholder);
|
||||
|
||||
// to avoid screen jitter, we first create the editor with position:absolute, visibility:hidden,
|
||||
// and then when it's finished rendering, we switch from display mode to editor
|
||||
var ews = ew.domNode.style;
|
||||
this.displayNode.style.display="none";
|
||||
ews.position = "static";
|
||||
ews.visibility = "visible";
|
||||
|
||||
// Replace the display widget with edit widget, leaving them both displayed for a brief time so that
|
||||
// focus can be shifted without incident. (browser may needs some time to render the editor.)
|
||||
this.domNode = ew.domNode;
|
||||
setTimeout(function(){
|
||||
ew.focus();
|
||||
}, 100);
|
||||
},
|
||||
|
||||
_showText: function(/*Boolean*/ focus){
|
||||
// summary: revert to display mode, and optionally focus on display node
|
||||
|
||||
// display the read-only text and then quickly hide the editor (to avoid screen jitter)
|
||||
this.displayNode.style.display="";
|
||||
var ews = this.editWidget.domNode.style;
|
||||
ews.position="absolute";
|
||||
ews.visibility="hidden";
|
||||
|
||||
this.domNode = this.displayNode;
|
||||
|
||||
// give the browser some time to render the display node and then shift focus to it
|
||||
// and hide the edit widget
|
||||
var _this = this;
|
||||
setTimeout(function(){
|
||||
if(focus){
|
||||
dijit.focus(_this.displayNode);
|
||||
}
|
||||
_this.editWidget.destroy();
|
||||
delete _this.editWidget;
|
||||
}, 100);
|
||||
},
|
||||
|
||||
save: function(/*Boolean*/ focus){
|
||||
// summary
|
||||
// Save the contents of the editor and revert to display mode.
|
||||
// focus: Boolean
|
||||
// Focus on the display mode text
|
||||
this.editing = false;
|
||||
|
||||
this.value = this.editWidget.getValue() + "";
|
||||
if(this.renderAsHtml){
|
||||
this.value = this.value.replace(/&/gm, "&").replace(/</gm, "<").replace(/>/gm, ">").replace(/"/gm, """)
|
||||
.replace("\n", "<br>");
|
||||
}
|
||||
this._setDisplayValue(this.value);
|
||||
|
||||
// tell the world that we have changed
|
||||
this.onChange(this.value);
|
||||
|
||||
this._showText(focus);
|
||||
},
|
||||
|
||||
_setDisplayValue: function(/*String*/ val){
|
||||
// summary: inserts specified HTML value into this node, or an "input needed" character if node is blank
|
||||
this.displayNode.innerHTML = val || this.noValueIndicator;
|
||||
},
|
||||
|
||||
cancel: function(/*Boolean*/ focus){
|
||||
// summary:
|
||||
// Revert to display mode, discarding any changes made in the editor
|
||||
this.editing = false;
|
||||
this._showText(focus);
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare(
|
||||
"dijit._InlineEditor",
|
||||
[dijit._Widget, dijit._Templated],
|
||||
{
|
||||
// summary:
|
||||
// internal widget used by InlineEditBox, displayed when in editing mode
|
||||
// to display the editor and maybe save/cancel buttons. Calling code should
|
||||
// connect to save/cancel methods to detect when editing is finished
|
||||
//
|
||||
// Has mainly the same parameters as InlineEditBox, plus these values:
|
||||
//
|
||||
// style: Object
|
||||
// Set of CSS attributes of display node, to replicate in editor
|
||||
//
|
||||
// value: String
|
||||
// Value as an HTML string or plain text string, depending on renderAsHTML flag
|
||||
|
||||
templateString:"<fieldset dojoAttachPoint=\"editNode\" waiRole=\"presentation\" style=\"position: absolute; visibility:hidden\" class=\"dijitReset dijitInline\"\n\tdojoAttachEvent=\"onkeypress: _onKeyPress\" \n\t><input dojoAttachPoint=\"editorPlaceholder\"\n\t/><span dojoAttachPoint=\"buttonContainer\"\n\t\t><button class='saveButton' dojoAttachPoint=\"saveButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:save\">${buttonSave}</button\n\t\t><button class='cancelButton' dojoAttachPoint=\"cancelButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:cancel\">${buttonCancel}</button\n\t></span\n></fieldset>\n",
|
||||
widgetsInTemplate: true,
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.inherited('postMixInProperties', arguments);
|
||||
this.messages = dojo.i18n.getLocalization("dijit", "common", this.lang);
|
||||
dojo.forEach(["buttonSave", "buttonCancel"], function(prop){
|
||||
if(!this[prop]){ this[prop] = this.messages[prop]; }
|
||||
}, this);
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
// Create edit widget in place in the template
|
||||
var cls = dojo.getObject(this.editor);
|
||||
var ew = this.editWidget = new cls(this.editorParams, this.editorPlaceholder);
|
||||
|
||||
// Copy the style from the source
|
||||
// Don't copy ALL properties though, just the necessary/applicable ones
|
||||
var srcStyle = this.style;
|
||||
dojo.forEach(["fontWeight","fontFamily","fontSize","fontStyle"], function(prop){
|
||||
ew.focusNode.style[prop]=srcStyle[prop];
|
||||
}, this);
|
||||
dojo.forEach(["marginTop","marginBottom","marginLeft", "marginRight"], function(prop){
|
||||
this.domNode.style[prop]=srcStyle[prop];
|
||||
}, this);
|
||||
if(this.width=="100%"){
|
||||
// block mode
|
||||
ew.domNode.style.width = "100%"; // because display: block doesn't work for table widgets
|
||||
this.domNode.style.display="block";
|
||||
}else{
|
||||
// inline-block mode
|
||||
ew.domNode.style.width = this.width + (Number(this.width)==this.width ? "px" : "");
|
||||
}
|
||||
|
||||
(this.editWidget.setDisplayedValue||this.editWidget.setValue).call(this.editWidget, this.value);
|
||||
this._initialText = this.getValue();
|
||||
|
||||
if(this.autoSave){
|
||||
this.buttonContainer.style.display="none";
|
||||
}
|
||||
|
||||
this.connect(this.editWidget, "onChange", "_onChange");
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
this.editWidget.destroy();
|
||||
this.inherited("destroy", arguments);
|
||||
},
|
||||
|
||||
getValue: function(){
|
||||
var ew = this.editWidget;
|
||||
return ew.getDisplayedValue ? ew.getDisplayedValue() : ew.getValue();
|
||||
},
|
||||
|
||||
_onKeyPress: function(e){
|
||||
// summary:
|
||||
// Callback when keypress in the edit box (see template).
|
||||
// For autoSave widgets, if Esc/Enter, call cancel/save.
|
||||
// For non-autoSave widgets, enable save button if the text value is
|
||||
// different than the original value.
|
||||
if(this._exitInProgress){
|
||||
return;
|
||||
}
|
||||
if(this.autoSave){
|
||||
// If Enter/Esc pressed, treat as save/cancel.
|
||||
if(e.keyCode == dojo.keys.ESCAPE){
|
||||
dojo.stopEvent(e);
|
||||
this._exitInProgress = true;
|
||||
this.cancel(true);
|
||||
}else if(e.keyCode == dojo.keys.ENTER){
|
||||
dojo.stopEvent(e);
|
||||
this._exitInProgress = true;
|
||||
this.save(true);
|
||||
}
|
||||
}else{
|
||||
var _this = this;
|
||||
// Delay before calling getValue().
|
||||
// The delay gives the browser a chance to update the Textarea.
|
||||
setTimeout(
|
||||
function(){
|
||||
_this.saveButton.setDisabled(_this.getValue() == _this._initialText);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
// summary:
|
||||
// Called when focus moves outside the editor
|
||||
if(this._exitInProgress){
|
||||
// when user clicks the "save" button, focus is shifted back to display text, causing this
|
||||
// function to be called, but in that case don't do anything
|
||||
return;
|
||||
}
|
||||
if(this.autoSave){
|
||||
this._exitInProgress = true;
|
||||
if(this.getValue() == this._initialText){
|
||||
this.cancel(false);
|
||||
}else{
|
||||
this.save(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
enableSave: function(){
|
||||
// summary: User replacable function returning a Boolean to indicate
|
||||
// if the Save button should be enabled or not - usually due to invalid conditions
|
||||
return this.editWidget.isValid ? this.editWidget.isValid() : true;
|
||||
},
|
||||
|
||||
_onChange: function(){
|
||||
// summary:
|
||||
// This is called when the underlying widget fires an onChange event,
|
||||
// which means that the user has finished entering the value
|
||||
if(this._exitInProgress){
|
||||
// TODO: the onChange event might happen after the return key for an async widget
|
||||
// like FilteringSelect. Shouldn't be deleting the edit widget on end-of-edit
|
||||
return;
|
||||
}
|
||||
if(this.autoSave){
|
||||
this._exitInProgress = true;
|
||||
this.save(true);
|
||||
}else{
|
||||
// in case the keypress event didn't get through (old problem with Textarea that has been fixed
|
||||
// in theory) or if the keypress event comes too quickly and the value inside the Textarea hasn't
|
||||
// been updated yet)
|
||||
this.saveButton.setDisabled((this.getValue() == this._initialText) || !this.enableSave());
|
||||
}
|
||||
},
|
||||
|
||||
enableSave: function(){
|
||||
// summary: User replacable function returning a Boolean to indicate
|
||||
// if the Save button should be enabled or not - usually due to invalid conditions
|
||||
return this.editWidget.isValid ? this.editWidget.isValid() : true;
|
||||
},
|
||||
|
||||
focus: function(){
|
||||
this.editWidget.focus();
|
||||
dijit.selectInputText(this.editWidget.focusNode);
|
||||
}
|
||||
});
|
||||
|
||||
dijit.selectInputText = function(/*DomNode*/element){
|
||||
// summary: select all the text in an input element (TODO: use functions in _editor/selection.js?)
|
||||
var _window = dojo.global;
|
||||
var _document = dojo.doc;
|
||||
element = dojo.byId(element);
|
||||
if(_document["selection"] && dojo.body()["createTextRange"]){ // IE
|
||||
if(element.createTextRange){
|
||||
var range = element.createTextRange();
|
||||
range.moveStart("character", 0);
|
||||
range.moveEnd("character", element.value.length);
|
||||
range.select();
|
||||
}
|
||||
}else if(_window["getSelection"]){
|
||||
var selection = _window.getSelection();
|
||||
// FIXME: does this work on Safari?
|
||||
if(element.setSelectionRange){
|
||||
element.setSelectionRange(0, element.value.length);
|
||||
}
|
||||
}
|
||||
element.focus();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
@@ -1,195 +0,0 @@
|
||||
Dojo is availble under *either* the terms of the modified BSD license *or* the
|
||||
Academic Free License version 2.1. As a recipient of Dojo, you may choose which
|
||||
license to receive this code under (except as noted in per-module LICENSE
|
||||
files). Some modules may not be the copyright of the Dojo Foundation. These
|
||||
modules contain explicit declarations of copyright in both the LICENSE files in
|
||||
the directories in which they reside and in the code itself. No external
|
||||
contributions are allowed under licenses which are fundamentally incompatible
|
||||
with the AFL or BSD licenses that Dojo is distributed under.
|
||||
|
||||
The text of the AFL and BSD licenses is reproduced below.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
The "New" BSD License:
|
||||
**********************
|
||||
|
||||
Copyright (c) 2005-2007, The Dojo Foundation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the Dojo Foundation nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
The Academic Free License, v. 2.1:
|
||||
**********************************
|
||||
|
||||
This Academic Free License (the "License") applies to any original work of
|
||||
authorship (the "Original Work") whose owner (the "Licensor") has placed the
|
||||
following notice immediately following the copyright notice for the Original
|
||||
Work:
|
||||
|
||||
Licensed under the Academic Free License version 2.1
|
||||
|
||||
1) Grant of Copyright License. Licensor hereby grants You a world-wide,
|
||||
royalty-free, non-exclusive, perpetual, sublicenseable license to do the
|
||||
following:
|
||||
|
||||
a) to reproduce the Original Work in copies;
|
||||
|
||||
b) to prepare derivative works ("Derivative Works") based upon the Original
|
||||
Work;
|
||||
|
||||
c) to distribute copies of the Original Work and Derivative Works to the
|
||||
public;
|
||||
|
||||
d) to perform the Original Work publicly; and
|
||||
|
||||
e) to display the Original Work publicly.
|
||||
|
||||
2) Grant of Patent License. Licensor hereby grants You a world-wide,
|
||||
royalty-free, non-exclusive, perpetual, sublicenseable license, under patent
|
||||
claims owned or controlled by the Licensor that are embodied in the Original
|
||||
Work as furnished by the Licensor, to make, use, sell and offer for sale the
|
||||
Original Work and Derivative Works.
|
||||
|
||||
3) Grant of Source Code License. The term "Source Code" means the preferred
|
||||
form of the Original Work for making modifications to it and all available
|
||||
documentation describing how to modify the Original Work. Licensor hereby
|
||||
agrees to provide a machine-readable copy of the Source Code of the Original
|
||||
Work along with each copy of the Original Work that Licensor distributes.
|
||||
Licensor reserves the right to satisfy this obligation by placing a
|
||||
machine-readable copy of the Source Code in an information repository
|
||||
reasonably calculated to permit inexpensive and convenient access by You for as
|
||||
long as Licensor continues to distribute the Original Work, and by publishing
|
||||
the address of that information repository in a notice immediately following
|
||||
the copyright notice that applies to the Original Work.
|
||||
|
||||
4) Exclusions From License Grant. Neither the names of Licensor, nor the names
|
||||
of any contributors to the Original Work, nor any of their trademarks or
|
||||
service marks, may be used to endorse or promote products derived from this
|
||||
Original Work without express prior written permission of the Licensor. Nothing
|
||||
in this License shall be deemed to grant any rights to trademarks, copyrights,
|
||||
patents, trade secrets or any other intellectual property of Licensor except as
|
||||
expressly stated herein. No patent license is granted to make, use, sell or
|
||||
offer to sell embodiments of any patent claims other than the licensed claims
|
||||
defined in Section 2. No right is granted to the trademarks of Licensor even if
|
||||
such marks are included in the Original Work. Nothing in this License shall be
|
||||
interpreted to prohibit Licensor from licensing under different terms from this
|
||||
License any Original Work that Licensor otherwise would have a right to
|
||||
license.
|
||||
|
||||
5) This section intentionally omitted.
|
||||
|
||||
6) Attribution Rights. You must retain, in the Source Code of any Derivative
|
||||
Works that You create, all copyright, patent or trademark notices from the
|
||||
Source Code of the Original Work, as well as any notices of licensing and any
|
||||
descriptive text identified therein as an "Attribution Notice." You must cause
|
||||
the Source Code for any Derivative Works that You create to carry a prominent
|
||||
Attribution Notice reasonably calculated to inform recipients that You have
|
||||
modified the Original Work.
|
||||
|
||||
7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that
|
||||
the copyright in and to the Original Work and the patent rights granted herein
|
||||
by Licensor are owned by the Licensor or are sublicensed to You under the terms
|
||||
of this License with the permission of the contributor(s) of those copyrights
|
||||
and patent rights. Except as expressly stated in the immediately proceeding
|
||||
sentence, the Original Work is provided under this License on an "AS IS" BASIS
|
||||
and WITHOUT WARRANTY, either express or implied, including, without limitation,
|
||||
the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.
|
||||
This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No
|
||||
license to Original Work is granted hereunder except under this disclaimer.
|
||||
|
||||
8) Limitation of Liability. Under no circumstances and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise, shall the
|
||||
Licensor be liable to any person for any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License
|
||||
or the use of the Original Work including, without limitation, damages for loss
|
||||
of goodwill, work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses. This limitation of liability shall not
|
||||
apply to liability for death or personal injury resulting from Licensor's
|
||||
negligence to the extent applicable law prohibits such limitation. Some
|
||||
jurisdictions do not allow the exclusion or limitation of incidental or
|
||||
consequential damages, so this exclusion and limitation may not apply to You.
|
||||
|
||||
9) Acceptance and Termination. If You distribute copies of the Original Work or
|
||||
a Derivative Work, You must make a reasonable effort under the circumstances to
|
||||
obtain the express assent of recipients to the terms of this License. Nothing
|
||||
else but this License (or another written agreement between Licensor and You)
|
||||
grants You permission to create Derivative Works based upon the Original Work
|
||||
or to exercise any of the rights granted in Section 1 herein, and any attempt
|
||||
to do so except under the terms of this License (or another written agreement
|
||||
between Licensor and You) is expressly prohibited by U.S. copyright law, the
|
||||
equivalent laws of other countries, and by international treaty. Therefore, by
|
||||
exercising any of the rights granted to You in Section 1 herein, You indicate
|
||||
Your acceptance of this License and all of its terms and conditions.
|
||||
|
||||
10) Termination for Patent Action. This License shall terminate automatically
|
||||
and You may no longer exercise any of the rights granted to You by this License
|
||||
as of the date You commence an action, including a cross-claim or counterclaim,
|
||||
against Licensor or any licensee alleging that the Original Work infringes a
|
||||
patent. This termination provision shall not apply for an action alleging
|
||||
patent infringement by combinations of the Original Work with other software or
|
||||
hardware.
|
||||
|
||||
11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this
|
||||
License may be brought only in the courts of a jurisdiction wherein the
|
||||
Licensor resides or in which Licensor conducts its primary business, and under
|
||||
the laws of that jurisdiction excluding its conflict-of-law provisions. The
|
||||
application of the United Nations Convention on Contracts for the International
|
||||
Sale of Goods is expressly excluded. Any use of the Original Work outside the
|
||||
scope of this License or after its termination shall be subject to the
|
||||
requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et
|
||||
seq., the equivalent laws of other countries, and international treaty. This
|
||||
section shall survive the termination of this License.
|
||||
|
||||
12) Attorneys Fees. In any action to enforce the terms of this License or
|
||||
seeking damages relating thereto, the prevailing party shall be entitled to
|
||||
recover its costs and expenses, including, without limitation, reasonable
|
||||
attorneys' fees and costs incurred in connection with such action, including
|
||||
any appeal of such action. This section shall survive the termination of this
|
||||
License.
|
||||
|
||||
13) Miscellaneous. This License represents the complete agreement concerning
|
||||
the subject matter hereof. If any provision of this License is held to be
|
||||
unenforceable, such provision shall be reformed only to the extent necessary to
|
||||
make it enforceable.
|
||||
|
||||
14) Definition of "You" in This License. "You" throughout this License, whether
|
||||
in upper or lower case, means an individual or a legal entity exercising rights
|
||||
under, and complying with all of the terms of, this License. For legal
|
||||
entities, "You" includes any entity that controls, is controlled by, or is
|
||||
under common control with you. For purposes of this definition, "control" means
|
||||
(i) the power, direct or indirect, to cause the direction or management of such
|
||||
entity, whether by contract or otherwise, or (ii) ownership of fifty percent
|
||||
(50%) or more of the outstanding shares, or (iii) beneficial ownership of such
|
||||
entity.
|
||||
|
||||
15) Right to Use. You may use the Original Work in all ways not otherwise
|
||||
restricted or conditioned by this License or by law, and Licensor promises not
|
||||
to interfere with or be responsible for such uses by You.
|
||||
|
||||
This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.
|
||||
Permission is hereby granted to copy and distribute this license without
|
||||
modification. This license may not be modified without the express written
|
||||
permission of its copyright owner.
|
||||
@@ -1,457 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.Menu"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.Menu"] = true;
|
||||
dojo.provide("dijit.Menu");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Container");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.Menu",
|
||||
[dijit._Widget, dijit._Templated, dijit._KeyNavContainer],
|
||||
{
|
||||
constructor: function() {
|
||||
this._bindings = [];
|
||||
},
|
||||
|
||||
templateString:
|
||||
'<table class="dijit dijitMenu dijitReset dijitMenuTable" waiRole="menu" dojoAttachEvent="onkeypress:_onKeyPress">' +
|
||||
'<tbody class="dijitReset" dojoAttachPoint="containerNode"></tbody>'+
|
||||
'</table>',
|
||||
|
||||
// targetNodeIds: String[]
|
||||
// Array of dom node ids of nodes to attach to.
|
||||
// Fill this with nodeIds upon widget creation and it becomes context menu for those nodes.
|
||||
targetNodeIds: [],
|
||||
|
||||
// contextMenuForWindow: Boolean
|
||||
// if true, right clicking anywhere on the window will cause this context menu to open;
|
||||
// if false, must specify targetNodeIds
|
||||
contextMenuForWindow: false,
|
||||
|
||||
// parentMenu: Widget
|
||||
// pointer to menu that displayed me
|
||||
parentMenu: null,
|
||||
|
||||
// popupDelay: Integer
|
||||
// number of milliseconds before hovering (without clicking) causes the popup to automatically open
|
||||
popupDelay: 500,
|
||||
|
||||
// _contextMenuWithMouse: Boolean
|
||||
// used to record mouse and keyboard events to determine if a context
|
||||
// menu is being opened with the keyboard or the mouse
|
||||
_contextMenuWithMouse: false,
|
||||
|
||||
postCreate: function(){
|
||||
if(this.contextMenuForWindow){
|
||||
this.bindDomNode(dojo.body());
|
||||
}else{
|
||||
dojo.forEach(this.targetNodeIds, this.bindDomNode, this);
|
||||
}
|
||||
this.connectKeyNavHandlers([dojo.keys.UP_ARROW], [dojo.keys.DOWN_ARROW]);
|
||||
},
|
||||
|
||||
startup: function(){
|
||||
dojo.forEach(this.getChildren(), function(child){ child.startup(); });
|
||||
this.startupKeyNavChildren();
|
||||
},
|
||||
|
||||
onExecute: function(){
|
||||
// summary: attach point for notification about when a menu item has been executed
|
||||
},
|
||||
|
||||
onCancel: function(/*Boolean*/ closeAll){
|
||||
// summary: attach point for notification about when the user cancels the current menu
|
||||
},
|
||||
|
||||
_moveToPopup: function(/*Event*/ evt){
|
||||
if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){
|
||||
this.focusedChild._onClick(evt);
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyPress: function(/*Event*/ evt){
|
||||
// summary
|
||||
// Handle keyboard based menu navigation.
|
||||
if(evt.ctrlKey || evt.altKey){ return; }
|
||||
|
||||
switch(evt.keyCode){
|
||||
case dojo.keys.RIGHT_ARROW:
|
||||
this._moveToPopup(evt);
|
||||
dojo.stopEvent(evt);
|
||||
break;
|
||||
case dojo.keys.LEFT_ARROW:
|
||||
if(this.parentMenu){
|
||||
this.onCancel(false);
|
||||
}else{
|
||||
dojo.stopEvent(evt);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
onItemHover: function(/*MenuItem*/ item){
|
||||
this.focusChild(item);
|
||||
|
||||
if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){
|
||||
this.hover_timer = setTimeout(dojo.hitch(this, "_openPopup"), this.popupDelay);
|
||||
}
|
||||
},
|
||||
|
||||
_onChildBlur: function(item){
|
||||
// Close all popups that are open and descendants of this menu
|
||||
dijit.popup.close(item.popup);
|
||||
item._blur();
|
||||
this._stopPopupTimer();
|
||||
},
|
||||
|
||||
onItemUnhover: function(/*MenuItem*/ item){
|
||||
},
|
||||
|
||||
_stopPopupTimer: function(){
|
||||
if(this.hover_timer){
|
||||
clearTimeout(this.hover_timer);
|
||||
this.hover_timer = null;
|
||||
}
|
||||
},
|
||||
|
||||
_getTopMenu: function(){
|
||||
for(var top=this; top.parentMenu; top=top.parentMenu);
|
||||
return top;
|
||||
},
|
||||
|
||||
onItemClick: function(/*Widget*/ item){
|
||||
// summary: user defined function to handle clicks on an item
|
||||
// summary: internal function for clicks
|
||||
if(item.disabled){ return false; }
|
||||
|
||||
if(item.popup){
|
||||
if(!this.is_open){
|
||||
this._openPopup();
|
||||
}
|
||||
}else{
|
||||
// before calling user defined handler, close hierarchy of menus
|
||||
// and restore focus to place it was when menu was opened
|
||||
this.onExecute();
|
||||
|
||||
// user defined handler for click
|
||||
item.onClick();
|
||||
}
|
||||
},
|
||||
|
||||
// thanks burstlib!
|
||||
_iframeContentWindow: function(/* HTMLIFrameElement */iframe_el) {
|
||||
// summary
|
||||
// returns the window reference of the passed iframe
|
||||
var win = dijit.getDocumentWindow(dijit.Menu._iframeContentDocument(iframe_el)) ||
|
||||
// Moz. TODO: is this available when defaultView isn't?
|
||||
dijit.Menu._iframeContentDocument(iframe_el)['__parent__'] ||
|
||||
(iframe_el.name && document.frames[iframe_el.name]) || null;
|
||||
return win; // Window
|
||||
},
|
||||
|
||||
_iframeContentDocument: function(/* HTMLIFrameElement */iframe_el){
|
||||
// summary
|
||||
// returns a reference to the document object inside iframe_el
|
||||
var doc = iframe_el.contentDocument // W3
|
||||
|| (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE
|
||||
|| (iframe_el.name && document.frames[iframe_el.name] && document.frames[iframe_el.name].document)
|
||||
|| null;
|
||||
return doc; // HTMLDocument
|
||||
},
|
||||
|
||||
bindDomNode: function(/*String|DomNode*/ node){
|
||||
// summary: attach menu to given node
|
||||
node = dojo.byId(node);
|
||||
|
||||
//TODO: this is to support context popups in Editor. Maybe this shouldn't be in dijit.Menu
|
||||
var win = dijit.getDocumentWindow(node.ownerDocument);
|
||||
if(node.tagName.toLowerCase()=="iframe"){
|
||||
win = this._iframeContentWindow(node);
|
||||
node = dojo.withGlobal(win, dojo.body);
|
||||
}
|
||||
|
||||
// to capture these events at the top level,
|
||||
// attach to document, not body
|
||||
var cn = (node == dojo.body() ? dojo.doc : node);
|
||||
|
||||
node[this.id] = this._bindings.push([
|
||||
dojo.connect(cn, "oncontextmenu", this, "_openMyself"),
|
||||
dojo.connect(cn, "onkeydown", this, "_contextKey"),
|
||||
dojo.connect(cn, "onmousedown", this, "_contextMouse")
|
||||
]);
|
||||
},
|
||||
|
||||
unBindDomNode: function(/*String|DomNode*/ nodeName){
|
||||
// summary: detach menu from given node
|
||||
var node = dojo.byId(nodeName);
|
||||
var bid = node[this.id]-1, b = this._bindings[bid];
|
||||
dojo.forEach(b, dojo.disconnect);
|
||||
delete this._bindings[bid];
|
||||
},
|
||||
|
||||
_contextKey: function(e){
|
||||
this._contextMenuWithMouse = false;
|
||||
if (e.keyCode == dojo.keys.F10) {
|
||||
dojo.stopEvent(e);
|
||||
if (e.shiftKey && e.type=="keydown") {
|
||||
// FF: copying the wrong property from e will cause the system
|
||||
// context menu to appear in spite of stopEvent. Don't know
|
||||
// exactly which properties cause this effect.
|
||||
var _e = { target: e.target, pageX: e.pageX, pageY: e.pageY };
|
||||
_e.preventDefault = _e.stopPropagation = function(){};
|
||||
// IE: without the delay, focus work in "open" causes the system
|
||||
// context menu to appear in spite of stopEvent.
|
||||
window.setTimeout(dojo.hitch(this, function(){ this._openMyself(_e); }), 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_contextMouse: function(e){
|
||||
this._contextMenuWithMouse = true;
|
||||
},
|
||||
|
||||
_openMyself: function(/*Event*/ e){
|
||||
// summary:
|
||||
// Internal function for opening myself when the user
|
||||
// does a right-click or something similar
|
||||
|
||||
dojo.stopEvent(e);
|
||||
|
||||
// Get coordinates.
|
||||
// if we are opening the menu with the mouse or on safari open
|
||||
// the menu at the mouse cursor
|
||||
// (Safari does not have a keyboard command to open the context menu
|
||||
// and we don't currently have a reliable way to determine
|
||||
// _contextMenuWithMouse on Safari)
|
||||
var x,y;
|
||||
if(dojo.isSafari || this._contextMenuWithMouse){
|
||||
x=e.pageX;
|
||||
y=e.pageY;
|
||||
}else{
|
||||
// otherwise open near e.target
|
||||
var coords = dojo.coords(e.target, true);
|
||||
x = coords.x + 10;
|
||||
y = coords.y + 10;
|
||||
}
|
||||
|
||||
var self=this;
|
||||
var savedFocus = dijit.getFocus(this);
|
||||
function closeAndRestoreFocus(){
|
||||
// user has clicked on a menu or popup
|
||||
dijit.focus(savedFocus);
|
||||
dijit.popup.close(self);
|
||||
}
|
||||
dijit.popup.open({
|
||||
popup: this,
|
||||
x: x,
|
||||
y: y,
|
||||
onExecute: closeAndRestoreFocus,
|
||||
onCancel: closeAndRestoreFocus,
|
||||
orient: this.isLeftToRight() ? 'L' : 'R'
|
||||
});
|
||||
this.focus();
|
||||
|
||||
this._onBlur = function(){
|
||||
// Usually the parent closes the child widget but if this is a context
|
||||
// menu then there is no parent
|
||||
dijit.popup.close(this);
|
||||
// don't try to restore focus; user has clicked another part of the screen
|
||||
// and set focus there
|
||||
}
|
||||
},
|
||||
|
||||
onOpen: function(/*Event*/ e){
|
||||
// summary
|
||||
// Open menu relative to the mouse
|
||||
this.isShowingNow = true;
|
||||
},
|
||||
|
||||
onClose: function(){
|
||||
// summary: callback when this menu is closed
|
||||
this._stopPopupTimer();
|
||||
this.parentMenu = null;
|
||||
this.isShowingNow = false;
|
||||
this.currentPopup = null;
|
||||
if(this.focusedChild){
|
||||
this._onChildBlur(this.focusedChild);
|
||||
this.focusedChild = null;
|
||||
}
|
||||
},
|
||||
|
||||
_openPopup: function(){
|
||||
// summary: open the popup to the side of the current menu item
|
||||
this._stopPopupTimer();
|
||||
var from_item = this.focusedChild;
|
||||
var popup = from_item.popup;
|
||||
|
||||
if(popup.isShowingNow){ return; }
|
||||
popup.parentMenu = this;
|
||||
var self = this;
|
||||
dijit.popup.open({
|
||||
parent: this,
|
||||
popup: popup,
|
||||
around: from_item.arrowCell,
|
||||
orient: this.isLeftToRight() ? {'TR': 'TL', 'TL': 'TR'} : {'TL': 'TR', 'TR': 'TL'},
|
||||
onCancel: function(){
|
||||
// called when the child menu is canceled
|
||||
dijit.popup.close(popup);
|
||||
from_item.focus(); // put focus back on my node
|
||||
self.currentPopup = null;
|
||||
}
|
||||
});
|
||||
|
||||
this.currentPopup = popup;
|
||||
|
||||
if(popup.focus){
|
||||
popup.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.MenuItem",
|
||||
[dijit._Widget, dijit._Templated, dijit._Contained],
|
||||
{
|
||||
// summary
|
||||
// A line item in a Menu2
|
||||
|
||||
// Make 3 columns
|
||||
// icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
|
||||
templateString:
|
||||
'<tr class="dijitReset dijitMenuItem"'
|
||||
+'dojoAttachEvent="onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick">'
|
||||
+'<td class="dijitReset"><div class="dijitMenuItemIcon ${iconClass}" dojoAttachPoint="iconNode" ></div></td>'
|
||||
+'<td tabIndex="-1" class="dijitReset dijitMenuItemLabel" dojoAttachPoint="containerNode" waiRole="menuitem"></td>'
|
||||
+'<td class="dijitReset" dojoAttachPoint="arrowCell">'
|
||||
+'<div class="dijitMenuExpand" dojoAttachPoint="expand" style="display:none">'
|
||||
+'<span class="dijitInline dijitArrowNode dijitMenuExpandInner">+</span>'
|
||||
+'</div>'
|
||||
+'</td>'
|
||||
+'</tr>',
|
||||
|
||||
// label: String
|
||||
// menu text
|
||||
label: '',
|
||||
|
||||
// iconClass: String
|
||||
// class to apply to div in button to make it display an icon
|
||||
iconClass: "",
|
||||
|
||||
// disabled: Boolean
|
||||
// if true, the menu item is disabled
|
||||
// if false, the menu item is enabled
|
||||
disabled: false,
|
||||
|
||||
postCreate: function(){
|
||||
dojo.setSelectable(this.domNode, false);
|
||||
this.setDisabled(this.disabled);
|
||||
if(this.label){
|
||||
this.containerNode.innerHTML=this.label;
|
||||
}
|
||||
},
|
||||
|
||||
_onHover: function(){
|
||||
// summary: callback when mouse is moved onto menu item
|
||||
this.getParent().onItemHover(this);
|
||||
},
|
||||
|
||||
_onUnhover: function(){
|
||||
// summary: callback when mouse is moved off of menu item
|
||||
// if we are unhovering the currently selected item
|
||||
// then unselect it
|
||||
this.getParent().onItemUnhover(this);
|
||||
},
|
||||
|
||||
_onClick: function(evt){
|
||||
this.getParent().onItemClick(this);
|
||||
dojo.stopEvent(evt);
|
||||
},
|
||||
|
||||
onClick: function() {
|
||||
// summary
|
||||
// User defined function to handle clicks
|
||||
},
|
||||
|
||||
focus: function(){
|
||||
dojo.addClass(this.domNode, 'dijitMenuItemHover');
|
||||
try{
|
||||
dijit.focus(this.containerNode);
|
||||
}catch(e){
|
||||
// this throws on IE (at least) in some scenarios
|
||||
}
|
||||
},
|
||||
|
||||
_blur: function(){
|
||||
dojo.removeClass(this.domNode, 'dijitMenuItemHover');
|
||||
},
|
||||
|
||||
setDisabled: function(/*Boolean*/ value){
|
||||
// summary: enable or disable this menu item
|
||||
this.disabled = value;
|
||||
dojo[value ? "addClass" : "removeClass"](this.domNode, 'dijitMenuItemDisabled');
|
||||
dijit.setWaiState(this.containerNode, 'disabled', value ? 'true' : 'false');
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare(
|
||||
"dijit.PopupMenuItem",
|
||||
dijit.MenuItem,
|
||||
{
|
||||
_fillContent: function(){
|
||||
// my inner HTML contains both the menu item text and a popup widget, like
|
||||
// <div dojoType="dijit.PopupMenuItem">
|
||||
// <span>pick me</span>
|
||||
// <popup> ... </popup>
|
||||
// </div>
|
||||
// the first part holds the menu item text and the second part is the popup
|
||||
if(this.srcNodeRef){
|
||||
var nodes = dojo.query("*", this.srcNodeRef);
|
||||
dijit.PopupMenuItem.superclass._fillContent.call(this, nodes[0]);
|
||||
|
||||
// save pointer to srcNode so we can grab the drop down widget after it's instantiated
|
||||
this.dropDownContainer = this.srcNodeRef;
|
||||
}
|
||||
},
|
||||
|
||||
startup: function(){
|
||||
// we didn't copy the dropdown widget from the this.srcNodeRef, so it's in no-man's
|
||||
// land now. move it to document.body.
|
||||
if(!this.popup){
|
||||
var node = dojo.query("[widgetId]", this.dropDownContainer)[0];
|
||||
this.popup = dijit.byNode(node);
|
||||
}
|
||||
dojo.body().appendChild(this.popup.domNode);
|
||||
|
||||
this.popup.domNode.style.display="none";
|
||||
dojo.addClass(this.expand, "dijitMenuExpandEnabled");
|
||||
dojo.style(this.expand, "display", "");
|
||||
dijit.setWaiState(this.containerNode, "haspopup", "true");
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare(
|
||||
"dijit.MenuSeparator",
|
||||
[dijit._Widget, dijit._Templated, dijit._Contained],
|
||||
{
|
||||
// summary
|
||||
// A line between two menu items
|
||||
|
||||
templateString: '<tr class="dijitMenuSeparator"><td colspan=3>'
|
||||
+'<div class="dijitMenuSeparatorTop"></div>'
|
||||
+'<div class="dijitMenuSeparatorBottom"></div>'
|
||||
+'</td></tr>',
|
||||
|
||||
postCreate: function(){
|
||||
dojo.setSelectable(this.domNode, false);
|
||||
},
|
||||
|
||||
isFocusable: function(){
|
||||
// summary:
|
||||
// over ride to always return false
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.ProgressBar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.ProgressBar"] = true;
|
||||
dojo.provide("dijit.ProgressBar");
|
||||
|
||||
dojo.require("dojo.fx");
|
||||
dojo.require("dojo.number");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare("dijit.ProgressBar", [dijit._Widget, dijit._Templated], {
|
||||
// summary:
|
||||
// a progress widget
|
||||
//
|
||||
// usage:
|
||||
// <div dojoType="ProgressBar"
|
||||
// places="0"
|
||||
// progress="..." maximum="..."></div>
|
||||
|
||||
// progress: String (Percentage or Number)
|
||||
// initial progress value.
|
||||
// with "%": percentage value, 0% <= progress <= 100%
|
||||
// or without "%": absolute value, 0 <= progress <= maximum
|
||||
progress: "0",
|
||||
|
||||
// maximum: Float
|
||||
// max sample number
|
||||
maximum: 100,
|
||||
|
||||
// places: Number
|
||||
// number of places to show in values; 0 by default
|
||||
places: 0,
|
||||
|
||||
// indeterminate: Boolean
|
||||
// false: show progress
|
||||
// true: show that a process is underway but that the progress is unknown
|
||||
indeterminate: false,
|
||||
|
||||
templateString:"<div class=\"dijitProgressBar dijitProgressBarEmpty\"\n\t><div waiRole=\"progressbar\" tabindex=\"0\" dojoAttachPoint=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\"></div\n\t\t><span style=\"visibility:hidden\"> </span\n\t></div\n\t><div dojoAttachPoint=\"label\" class=\"dijitProgressBarLabel\"> </div\n\t><img dojoAttachPoint=\"inteterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\"\n\t></img\n></div>\n",
|
||||
|
||||
_indeterminateHighContrastImagePath:
|
||||
dojo.moduleUrl("dijit", "themes/a11y/indeterminate_progress.gif"),
|
||||
|
||||
// public functions
|
||||
postCreate: function(){
|
||||
this.inherited("postCreate",arguments);
|
||||
this.inteterminateHighContrastImage.setAttribute("src",
|
||||
this._indeterminateHighContrastImagePath);
|
||||
this.update();
|
||||
},
|
||||
|
||||
update: function(/*Object?*/attributes){
|
||||
// summary: update progress information
|
||||
//
|
||||
// attributes: may provide progress and/or maximum properties on this parameter,
|
||||
// see attribute specs for details.
|
||||
dojo.mixin(this, attributes||{});
|
||||
var percent = 1, classFunc;
|
||||
if(this.indeterminate){
|
||||
classFunc = "addClass";
|
||||
dijit.removeWaiState(this.internalProgress, "valuenow");
|
||||
dijit.removeWaiState(this.internalProgress, "valuemin");
|
||||
dijit.removeWaiState(this.internalProgress, "valuemax");
|
||||
}else{
|
||||
classFunc = "removeClass";
|
||||
if(String(this.progress).indexOf("%") != -1){
|
||||
percent = Math.min(parseFloat(this.progress)/100, 1);
|
||||
this.progress = percent * this.maximum;
|
||||
}else{
|
||||
this.progress = Math.min(this.progress, this.maximum);
|
||||
percent = this.progress / this.maximum;
|
||||
}
|
||||
var text = this.report(percent);
|
||||
this.label.firstChild.nodeValue = text;
|
||||
dijit.setWaiState(this.internalProgress, "valuenow", this.progress);
|
||||
dijit.setWaiState(this.internalProgress, "valuemin", 0);
|
||||
dijit.setWaiState(this.internalProgress, "valuemax", this.maximum);
|
||||
}
|
||||
dojo[classFunc](this.domNode, "dijitProgressBarIndeterminate");
|
||||
this.internalProgress.style.width = (percent * 100) + "%";
|
||||
this.onChange();
|
||||
},
|
||||
|
||||
report: function(/*float*/percent){
|
||||
// Generates message to show; may be overridden by user
|
||||
return dojo.number.format(percent, {type: "percent", places: this.places, locale: this.lang});
|
||||
},
|
||||
|
||||
onChange: function(){}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.TitlePane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.TitlePane"] = true;
|
||||
dojo.provide("dijit.TitlePane");
|
||||
|
||||
dojo.require("dojo.fx");
|
||||
|
||||
dojo.require("dijit._Templated");
|
||||
dojo.require("dijit.layout.ContentPane");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.TitlePane",
|
||||
[dijit.layout.ContentPane, dijit._Templated],
|
||||
{
|
||||
// summary
|
||||
// A pane with a title on top, that can be opened or collapsed.
|
||||
//
|
||||
// title: String
|
||||
// Title of the pane
|
||||
title: "",
|
||||
|
||||
// open: Boolean
|
||||
// Whether pane is opened or closed.
|
||||
open: true,
|
||||
|
||||
// duration: Integer
|
||||
// Time in milliseconds to fade in/fade out
|
||||
duration: 250,
|
||||
|
||||
// baseClass: String
|
||||
// the root className to use for the various states of this widget
|
||||
baseClass: "dijitTitlePane",
|
||||
|
||||
templateString:"<div class=\"dijitTitlePane\">\n\t<div dojoAttachEvent=\"onclick:toggle,onkeypress: _onTitleKey,onfocus:_handleFocus,onblur:_handleFocus\" tabindex=\"0\"\n\t\t\twaiRole=\"button\" class=\"dijitTitlePaneTitle\" dojoAttachPoint=\"focusNode\">\n\t\t<div dojoAttachPoint=\"arrowNode\" class=\"dijitInline dijitArrowNode\"><span dojoAttachPoint=\"arrowNodeInner\" class=\"dijitArrowNodeInner\"></span></div>\n\t\t<div dojoAttachPoint=\"titleNode\" class=\"dijitTitlePaneTextNode\"></div>\n\t</div>\n\t<div class=\"dijitTitlePaneContentOuter\" dojoAttachPoint=\"hideNode\">\n\t\t<div class=\"dijitReset\" dojoAttachPoint=\"wipeNode\">\n\t\t\t<div class=\"dijitTitlePaneContentInner\" dojoAttachPoint=\"containerNode\" waiRole=\"region\" tabindex=\"-1\">\n\t\t\t\t<!-- nested divs because wipeIn()/wipeOut() doesn't work right on node w/padding etc. Put padding on inner div. -->\n\t\t\t</div>\n\t\t</div>\n\t</div>\n</div>\n",
|
||||
|
||||
postCreate: function(){
|
||||
this.setTitle(this.title);
|
||||
if(!this.open){
|
||||
this.hideNode.style.display = this.wipeNode.style.display = "none";
|
||||
}
|
||||
this._setCss();
|
||||
dojo.setSelectable(this.titleNode, false);
|
||||
this.inherited("postCreate",arguments);
|
||||
dijit.setWaiState(this.containerNode, "labelledby", this.titleNode.id);
|
||||
dijit.setWaiState(this.focusNode, "haspopup", "true");
|
||||
|
||||
// setup open/close animations
|
||||
var hideNode = this.hideNode, wipeNode = this.wipeNode;
|
||||
this._wipeIn = dojo.fx.wipeIn({
|
||||
node: this.wipeNode,
|
||||
duration: this.duration,
|
||||
beforeBegin: function(){
|
||||
hideNode.style.display="";
|
||||
}
|
||||
});
|
||||
this._wipeOut = dojo.fx.wipeOut({
|
||||
node: this.wipeNode,
|
||||
duration: this.duration,
|
||||
onEnd: function(){
|
||||
hideNode.style.display="none";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setContent: function(content){
|
||||
// summary
|
||||
// Typically called when an href is loaded. Our job is to make the animation smooth
|
||||
if(this._wipeOut.status() == "playing"){
|
||||
// we are currently *closing* the pane, so just let that continue
|
||||
this.inherited("setContent",arguments);
|
||||
}else{
|
||||
if(this._wipeIn.status() == "playing"){
|
||||
this._wipeIn.stop();
|
||||
}
|
||||
|
||||
// freeze container at current height so that adding new content doesn't make it jump
|
||||
dojo.marginBox(this.wipeNode, {h: dojo.marginBox(this.wipeNode).h});
|
||||
|
||||
// add the new content (erasing the old content, if any)
|
||||
this.inherited("setContent",arguments);
|
||||
|
||||
// call _wipeIn.play() to animate from current height to new height
|
||||
this._wipeIn.play();
|
||||
}
|
||||
},
|
||||
|
||||
toggle: function(){
|
||||
// summary: switches between opened and closed state
|
||||
dojo.forEach([this._wipeIn, this._wipeOut], function(animation){
|
||||
if(animation.status() == "playing"){
|
||||
animation.stop();
|
||||
}
|
||||
});
|
||||
|
||||
this[this.open ? "_wipeOut" : "_wipeIn"].play();
|
||||
this.open =! this.open;
|
||||
|
||||
// load content (if this is the first time we are opening the TitlePane
|
||||
// and content is specified as an href, or we have setHref when hidden)
|
||||
this._loadCheck();
|
||||
|
||||
this._setCss();
|
||||
},
|
||||
|
||||
_setCss: function(){
|
||||
// summary: set the open/close css state for the TitlePane
|
||||
var classes = ["dijitClosed", "dijitOpen"];
|
||||
var boolIndex = this.open;
|
||||
dojo.removeClass(this.focusNode, classes[!boolIndex+0]);
|
||||
this.focusNode.className += " " + classes[boolIndex+0];
|
||||
|
||||
// provide a character based indicator for images-off mode
|
||||
this.arrowNodeInner.innerHTML = this.open ? "-" : "+";
|
||||
},
|
||||
|
||||
_onTitleKey: function(/*Event*/ e){
|
||||
// summary: callback when user hits a key
|
||||
if(e.keyCode == dojo.keys.ENTER || e.charCode == dojo.keys.SPACE){
|
||||
this.toggle();
|
||||
}
|
||||
else if(e.keyCode == dojo.keys.DOWN_ARROW){
|
||||
if(this.open){
|
||||
this.containerNode.focus();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_handleFocus: function(/*Event*/ e){
|
||||
// summary: handle blur and focus for this widget
|
||||
|
||||
// add/removeClass is safe to call without hasClass in this case
|
||||
dojo[(e.type=="focus" ? "addClass" : "removeClass")](this.focusNode,this.baseClass+"Focused");
|
||||
},
|
||||
|
||||
setTitle: function(/*String*/ title){
|
||||
// summary: sets the text of the title
|
||||
this.titleNode.innerHTML=title;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.Toolbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.Toolbar"] = true;
|
||||
dojo.provide("dijit.Toolbar");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Container");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.Toolbar",
|
||||
[dijit._Widget, dijit._Templated, dijit._KeyNavContainer],
|
||||
{
|
||||
templateString:
|
||||
'<div class="dijit dijitToolbar" waiRole="toolbar" tabIndex="${tabIndex}" dojoAttachPoint="containerNode">' +
|
||||
// '<table style="table-layout: fixed" class="dijitReset dijitToolbarTable">' + // factor out style
|
||||
// '<tr class="dijitReset" dojoAttachPoint="containerNode"></tr>'+
|
||||
// '</table>' +
|
||||
'</div>',
|
||||
|
||||
tabIndex: "0",
|
||||
|
||||
postCreate: function(){
|
||||
this.connectKeyNavHandlers(
|
||||
this.isLeftToRight() ? [dojo.keys.LEFT_ARROW] : [dojo.keys.RIGHT_ARROW],
|
||||
this.isLeftToRight() ? [dojo.keys.RIGHT_ARROW] : [dojo.keys.LEFT_ARROW]
|
||||
);
|
||||
},
|
||||
|
||||
startup: function(){
|
||||
this.startupKeyNavChildren();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Combine with dijit.MenuSeparator??
|
||||
dojo.declare(
|
||||
"dijit.ToolbarSeparator",
|
||||
[ dijit._Widget, dijit._Templated ],
|
||||
{
|
||||
// summary
|
||||
// A line between two menu items
|
||||
templateString: '<div class="dijitToolbarSeparator dijitInline"></div>',
|
||||
postCreate: function(){ dojo.setSelectable(this.domNode, false); },
|
||||
isFocusable: function(){ return false; }
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,230 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.Tooltip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.Tooltip"] = true;
|
||||
dojo.provide("dijit.Tooltip");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare(
|
||||
"dijit._MasterTooltip",
|
||||
[dijit._Widget, dijit._Templated],
|
||||
{
|
||||
// summary
|
||||
// Internal widget that holds the actual tooltip markup,
|
||||
// which occurs once per page.
|
||||
// Called by Tooltip widgets which are just containers to hold
|
||||
// the markup
|
||||
|
||||
// duration: Integer
|
||||
// Milliseconds to fade in/fade out
|
||||
duration: 200,
|
||||
|
||||
templateString:"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\">\n\t<div class=\"dijitTooltipContainer dijitTooltipContents\" dojoAttachPoint=\"containerNode\" waiRole='alert'></div>\n\t<div class=\"dijitTooltipConnector\"></div>\n</div>\n",
|
||||
|
||||
postCreate: function(){
|
||||
dojo.body().appendChild(this.domNode);
|
||||
|
||||
this.bgIframe = new dijit.BackgroundIframe(this.domNode);
|
||||
|
||||
// Setup fade-in and fade-out functions.
|
||||
this.fadeIn = dojo.fadeIn({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onShow") });
|
||||
this.fadeOut = dojo.fadeOut({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onHide") });
|
||||
|
||||
},
|
||||
|
||||
show: function(/*String*/ innerHTML, /*DomNode*/ aroundNode){
|
||||
// summary:
|
||||
// Display tooltip w/specified contents to right specified node
|
||||
// (To left if there's no space on the right, or if LTR==right)
|
||||
|
||||
if(this.aroundNode && this.aroundNode === aroundNode){
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.fadeOut.status() == "playing"){
|
||||
// previous tooltip is being hidden; wait until the hide completes then show new one
|
||||
this._onDeck=arguments;
|
||||
return;
|
||||
}
|
||||
this.containerNode.innerHTML=innerHTML;
|
||||
|
||||
// Firefox bug. when innerHTML changes to be shorter than previous
|
||||
// one, the node size will not be updated until it moves.
|
||||
this.domNode.style.top = (this.domNode.offsetTop + 1) + "px";
|
||||
|
||||
// position the element and change CSS according to position
|
||||
var align = this.isLeftToRight() ? {'BR': 'BL', 'BL': 'BR'} : {'BL': 'BR', 'BR': 'BL'};
|
||||
var pos = dijit.placeOnScreenAroundElement(this.domNode, aroundNode, align);
|
||||
this.domNode.className="dijitTooltip dijitTooltip" + (pos.corner=='BL' ? "Right" : "Left");//FIXME: might overwrite class
|
||||
|
||||
// show it
|
||||
dojo.style(this.domNode, "opacity", 0);
|
||||
this.fadeIn.play();
|
||||
this.isShowingNow = true;
|
||||
this.aroundNode = aroundNode;
|
||||
},
|
||||
|
||||
_onShow: function(){
|
||||
if(dojo.isIE){
|
||||
// the arrow won't show up on a node w/an opacity filter
|
||||
this.domNode.style.filter="";
|
||||
}
|
||||
},
|
||||
|
||||
hide: function(aroundNode){
|
||||
// summary: hide the tooltip
|
||||
if(!this.aroundNode || this.aroundNode !== aroundNode){
|
||||
return;
|
||||
}
|
||||
if(this._onDeck){
|
||||
// this hide request is for a show() that hasn't even started yet;
|
||||
// just cancel the pending show()
|
||||
this._onDeck=null;
|
||||
return;
|
||||
}
|
||||
this.fadeIn.stop();
|
||||
this.isShowingNow = false;
|
||||
this.aroundNode = null;
|
||||
this.fadeOut.play();
|
||||
},
|
||||
|
||||
_onHide: function(){
|
||||
this.domNode.style.cssText=""; // to position offscreen again
|
||||
if(this._onDeck){
|
||||
// a show request has been queued up; do it now
|
||||
this.show.apply(this, this._onDeck);
|
||||
this._onDeck=null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
dijit.showTooltip = function(/*String*/ innerHTML, /*DomNode*/ aroundNode){
|
||||
// summary:
|
||||
// Display tooltip w/specified contents to right specified node
|
||||
// (To left if there's no space on the right, or if LTR==right)
|
||||
if(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }
|
||||
return dijit._masterTT.show(innerHTML, aroundNode);
|
||||
};
|
||||
|
||||
dijit.hideTooltip = function(aroundNode){
|
||||
// summary: hide the tooltip
|
||||
if(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }
|
||||
return dijit._masterTT.hide(aroundNode);
|
||||
};
|
||||
|
||||
dojo.declare(
|
||||
"dijit.Tooltip",
|
||||
dijit._Widget,
|
||||
{
|
||||
// summary
|
||||
// Pops up a tooltip (a help message) when you hover over a node.
|
||||
|
||||
// label: String
|
||||
// Text to display in the tooltip.
|
||||
// Specified as innerHTML when creating the widget from markup.
|
||||
label: "",
|
||||
|
||||
// showDelay: Integer
|
||||
// Number of milliseconds to wait after hovering over/focusing on the object, before
|
||||
// the tooltip is displayed.
|
||||
showDelay: 400,
|
||||
|
||||
// connectId: String[]
|
||||
// Id(s) of domNodes to attach the tooltip to.
|
||||
// When user hovers over any of the specified dom nodes, the tooltip will appear.
|
||||
connectId: [],
|
||||
|
||||
postCreate: function(){
|
||||
if(this.srcNodeRef){
|
||||
this.srcNodeRef.style.display = "none";
|
||||
}
|
||||
|
||||
this._connectNodes = [];
|
||||
|
||||
dojo.forEach(this.connectId, function(id) {
|
||||
var node = dojo.byId(id);
|
||||
if (node) {
|
||||
this._connectNodes.push(node);
|
||||
dojo.forEach(["onMouseOver", "onMouseOut", "onFocus", "onBlur", "onHover", "onUnHover"], function(event){
|
||||
this.connect(node, event.toLowerCase(), "_"+event);
|
||||
}, this);
|
||||
if(dojo.isIE){
|
||||
// BiDi workaround
|
||||
node.style.zoom = 1;
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
_onMouseOver: function(/*Event*/ e){
|
||||
this._onHover(e);
|
||||
},
|
||||
|
||||
_onMouseOut: function(/*Event*/ e){
|
||||
if(dojo.isDescendant(e.relatedTarget, e.target)){
|
||||
// false event; just moved from target to target child; ignore.
|
||||
return;
|
||||
}
|
||||
this._onUnHover(e);
|
||||
},
|
||||
|
||||
_onFocus: function(/*Event*/ e){
|
||||
this._focus = true;
|
||||
this._onHover(e);
|
||||
},
|
||||
|
||||
_onBlur: function(/*Event*/ e){
|
||||
this._focus = false;
|
||||
this._onUnHover(e);
|
||||
},
|
||||
|
||||
_onHover: function(/*Event*/ e){
|
||||
if(!this._showTimer){
|
||||
var target = e.target;
|
||||
this._showTimer = setTimeout(dojo.hitch(this, function(){this.open(target)}), this.showDelay);
|
||||
}
|
||||
},
|
||||
|
||||
_onUnHover: function(/*Event*/ e){
|
||||
// keep a tooltip open if the associated element has focus
|
||||
if(this._focus){ return; }
|
||||
if(this._showTimer){
|
||||
clearTimeout(this._showTimer);
|
||||
delete this._showTimer;
|
||||
}
|
||||
this.close();
|
||||
},
|
||||
|
||||
open: function(/*DomNode*/ target){
|
||||
// summary: display the tooltip; usually not called directly.
|
||||
target = target || this._connectNodes[0];
|
||||
if(!target){ return; }
|
||||
|
||||
if(this._showTimer){
|
||||
clearTimeout(this._showTimer);
|
||||
delete this._showTimer;
|
||||
}
|
||||
dijit.showTooltip(this.label || this.domNode.innerHTML, target);
|
||||
|
||||
this._connectNode = target;
|
||||
},
|
||||
|
||||
close: function(){
|
||||
// summary: hide the tooltip; usually not called directly.
|
||||
dijit.hideTooltip(this._connectNode);
|
||||
delete this._connectNode;
|
||||
if(this._showTimer){
|
||||
clearTimeout(this._showTimer);
|
||||
delete this._showTimer;
|
||||
}
|
||||
},
|
||||
|
||||
uninitialize: function(){
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,908 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.Tree"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.Tree"] = true;
|
||||
dojo.provide("dijit.Tree");
|
||||
|
||||
dojo.require("dojo.fx");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
dojo.require("dijit._Container");
|
||||
dojo.require("dojo.cookie");
|
||||
|
||||
dojo.declare(
|
||||
"dijit._TreeNode",
|
||||
[dijit._Widget, dijit._Templated, dijit._Container, dijit._Contained],
|
||||
{
|
||||
// summary
|
||||
// Single node within a tree
|
||||
|
||||
// item: dojo.data.Item
|
||||
// the dojo.data entry this tree represents
|
||||
item: null,
|
||||
|
||||
isTreeNode: true,
|
||||
|
||||
// label: String
|
||||
// Text of this tree node
|
||||
label: "",
|
||||
|
||||
isExpandable: null, // show expando node
|
||||
|
||||
isExpanded: false,
|
||||
|
||||
// state: String
|
||||
// dynamic loading-related stuff.
|
||||
// When an empty folder node appears, it is "UNCHECKED" first,
|
||||
// then after dojo.data query it becomes "LOADING" and, finally "LOADED"
|
||||
state: "UNCHECKED",
|
||||
|
||||
templateString:"<div class=\"dijitTreeNode dijitTreeExpandLeaf dijitTreeChildrenNo\" waiRole=\"presentation\"\n\t><span dojoAttachPoint=\"expandoNode\" class=\"dijitTreeExpando\" waiRole=\"presentation\"\n\t></span\n\t><span dojoAttachPoint=\"expandoNodeText\" class=\"dijitExpandoText\" waiRole=\"presentation\"\n\t></span\n\t>\n\t<div dojoAttachPoint=\"contentNode\" class=\"dijitTreeContent\" waiRole=\"presentation\">\n\t\t<div dojoAttachPoint=\"iconNode\" class=\"dijitInline dijitTreeIcon\" waiRole=\"presentation\"></div>\n\t\t<span dojoAttachPoint=\"labelNode\" class=\"dijitTreeLabel\" wairole=\"treeitem\" tabindex=\"-1\"></span>\n\t</div>\n</div>\n",
|
||||
|
||||
postCreate: function(){
|
||||
// set label, escaping special characters
|
||||
this.setLabelNode(this.label);
|
||||
|
||||
// set expand icon for leaf
|
||||
this._setExpando();
|
||||
|
||||
// set icon and label class based on item
|
||||
this._updateItemClasses(this.item);
|
||||
|
||||
if(this.isExpandable){
|
||||
dijit.setWaiState(this.labelNode, "expanded", this.isExpanded);
|
||||
}
|
||||
},
|
||||
|
||||
markProcessing: function(){
|
||||
// summary: visually denote that tree is loading data, etc.
|
||||
this.state = "LOADING";
|
||||
this._setExpando(true);
|
||||
},
|
||||
|
||||
unmarkProcessing: function(){
|
||||
// summary: clear markup from markProcessing() call
|
||||
this._setExpando(false);
|
||||
},
|
||||
|
||||
_updateItemClasses: function(item){
|
||||
// summary: set appropriate CSS classes for item (used to allow for item updates to change respective CSS)
|
||||
this.iconNode.className = "dijitInline dijitTreeIcon " + this.tree.getIconClass(item);
|
||||
this.labelNode.className = "dijitTreeLabel " + this.tree.getLabelClass(item);
|
||||
},
|
||||
|
||||
_updateLayout: function(){
|
||||
// summary: set appropriate CSS classes for this.domNode
|
||||
var parent = this.getParent();
|
||||
if(parent && parent.isTree && parent._hideRoot){
|
||||
/* if we are hiding the root node then make every first level child look like a root node */
|
||||
dojo.addClass(this.domNode, "dijitTreeIsRoot");
|
||||
}else{
|
||||
dojo.toggleClass(this.domNode, "dijitTreeIsLast", !this.getNextSibling());
|
||||
}
|
||||
},
|
||||
|
||||
_setExpando: function(/*Boolean*/ processing){
|
||||
// summary: set the right image for the expando node
|
||||
|
||||
// apply the appropriate class to the expando node
|
||||
var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened",
|
||||
"dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"];
|
||||
var idx = processing ? 0 : (this.isExpandable ? (this.isExpanded ? 1 : 2) : 3);
|
||||
dojo.forEach(styles,
|
||||
function(s){
|
||||
dojo.removeClass(this.expandoNode, s);
|
||||
}, this
|
||||
);
|
||||
dojo.addClass(this.expandoNode, styles[idx]);
|
||||
|
||||
// provide a non-image based indicator for images-off mode
|
||||
this.expandoNodeText.innerHTML =
|
||||
processing ? "*" :
|
||||
(this.isExpandable ?
|
||||
(this.isExpanded ? "-" : "+") : "*");
|
||||
},
|
||||
|
||||
expand: function(){
|
||||
// summary: show my children
|
||||
if(this.isExpanded){ return; }
|
||||
// cancel in progress collapse operation
|
||||
if(this._wipeOut.status() == "playing"){
|
||||
this._wipeOut.stop();
|
||||
}
|
||||
|
||||
this.isExpanded = true;
|
||||
dijit.setWaiState(this.labelNode, "expanded", "true");
|
||||
dijit.setWaiRole(this.containerNode, "group");
|
||||
|
||||
this._setExpando();
|
||||
|
||||
this._wipeIn.play();
|
||||
},
|
||||
|
||||
collapse: function(){
|
||||
if(!this.isExpanded){ return; }
|
||||
|
||||
// cancel in progress expand operation
|
||||
if(this._wipeIn.status() == "playing"){
|
||||
this._wipeIn.stop();
|
||||
}
|
||||
|
||||
this.isExpanded = false;
|
||||
dijit.setWaiState(this.labelNode, "expanded", "false");
|
||||
this._setExpando();
|
||||
|
||||
this._wipeOut.play();
|
||||
},
|
||||
|
||||
setLabelNode: function(label){
|
||||
this.labelNode.innerHTML="";
|
||||
this.labelNode.appendChild(document.createTextNode(label));
|
||||
},
|
||||
|
||||
_setChildren: function(/* Object[] */ childrenArray){
|
||||
// summary:
|
||||
// Sets the children of this node.
|
||||
// Sets this.isExpandable based on whether or not there are children
|
||||
// Takes array of objects like: {label: ...} (_TreeNode options basically)
|
||||
// See parameters of _TreeNode for details.
|
||||
|
||||
this.destroyDescendants();
|
||||
|
||||
this.state = "LOADED";
|
||||
var nodeMap= {};
|
||||
if(childrenArray && childrenArray.length > 0){
|
||||
this.isExpandable = true;
|
||||
if(!this.containerNode){ // maybe this node was unfolderized and still has container
|
||||
this.containerNode = this.tree.containerNodeTemplate.cloneNode(true);
|
||||
this.domNode.appendChild(this.containerNode);
|
||||
}
|
||||
|
||||
// Create _TreeNode widget for each specified tree node
|
||||
dojo.forEach(childrenArray, function(childParams){
|
||||
var child = new dijit._TreeNode(dojo.mixin({
|
||||
tree: this.tree,
|
||||
label: this.tree.getLabel(childParams.item)
|
||||
}, childParams));
|
||||
this.addChild(child);
|
||||
var identity = this.tree.store.getIdentity(childParams.item);
|
||||
nodeMap[identity] = child;
|
||||
if(this.tree.persist){
|
||||
if(this.tree._openedItemIds[identity]){
|
||||
this.tree._expandNode(child);
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
|
||||
// note that updateLayout() needs to be called on each child after
|
||||
// _all_ the children exist
|
||||
dojo.forEach(this.getChildren(), function(child, idx){
|
||||
child._updateLayout();
|
||||
});
|
||||
}else{
|
||||
this.isExpandable=false;
|
||||
}
|
||||
|
||||
if(this._setExpando){
|
||||
// change expando to/form dot or + icon, as appropriate
|
||||
this._setExpando(false);
|
||||
}
|
||||
|
||||
if(this.isTree && this._hideRoot){
|
||||
// put first child in tab index if one exists.
|
||||
var fc = this.getChildren()[0];
|
||||
var tabnode = fc ? fc.labelNode : this.domNode;
|
||||
tabnode.setAttribute("tabIndex", "0");
|
||||
}
|
||||
|
||||
// create animations for showing/hiding the children (if children exist)
|
||||
if(this.containerNode && !this._wipeIn){
|
||||
this._wipeIn = dojo.fx.wipeIn({node: this.containerNode, duration: 150});
|
||||
this._wipeOut = dojo.fx.wipeOut({node: this.containerNode, duration: 150});
|
||||
}
|
||||
|
||||
return nodeMap;
|
||||
},
|
||||
|
||||
_addChildren: function(/* object[] */ childrenArray){
|
||||
// summary:
|
||||
// adds the children to this node.
|
||||
// Takes array of objects like: {label: ...} (_TreeNode options basically)
|
||||
|
||||
// See parameters of _TreeNode for details.
|
||||
var nodeMap = {};
|
||||
if(childrenArray && childrenArray.length > 0){
|
||||
dojo.forEach(childrenArray, function(childParams){
|
||||
var child = new dijit._TreeNode(
|
||||
dojo.mixin({
|
||||
tree: this.tree,
|
||||
label: this.tree.getLabel(childParams.item)
|
||||
}, childParams)
|
||||
);
|
||||
this.addChild(child);
|
||||
nodeMap[this.tree.store.getIdentity(childParams.item)] = child;
|
||||
}, this);
|
||||
|
||||
dojo.forEach(this.getChildren(), function(child, idx){
|
||||
child._updateLayout();
|
||||
});
|
||||
}
|
||||
|
||||
return nodeMap;
|
||||
},
|
||||
|
||||
deleteNode: function(/* treeNode */ node){
|
||||
node.destroy();
|
||||
|
||||
dojo.forEach(this.getChildren(), function(child, idx){
|
||||
child._updateLayout();
|
||||
});
|
||||
},
|
||||
|
||||
makeExpandable: function(){
|
||||
//summary
|
||||
// if this node wasn't already showing the expando node,
|
||||
// turn it into one and call _setExpando()
|
||||
this.isExpandable = true;
|
||||
this._setExpando(false);
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare(
|
||||
"dijit.Tree",
|
||||
dijit._TreeNode,
|
||||
{
|
||||
// summary
|
||||
// This widget displays hierarchical data from a store. A query is specified
|
||||
// to get the "top level children" from a data store, and then those items are
|
||||
// queried for their children and so on (but lazily, as the user clicks the expand node).
|
||||
//
|
||||
// Thus in the default mode of operation this widget is technically a forest, not a tree,
|
||||
// in that there can be multiple "top level children". However, if you specify label,
|
||||
// then a special top level node (not corresponding to any item in the datastore) is
|
||||
// created, to father all the top level children.
|
||||
|
||||
// store: String||dojo.data.Store
|
||||
// The store to get data to display in the tree
|
||||
store: null,
|
||||
|
||||
// query: String
|
||||
// query to get top level node(s) of tree (ex: {type:'continent'})
|
||||
query: null,
|
||||
|
||||
// childrenAttr: String
|
||||
// one ore more attributes that holds children of a tree node
|
||||
childrenAttr: ["children"],
|
||||
|
||||
templateString:"<div class=\"dijitTreeContainer\" style=\"\" waiRole=\"tree\"\n\tdojoAttachEvent=\"onclick:_onClick,onkeypress:_onKeyPress\">\n\t<div class=\"dijitTreeNode dijitTreeIsRoot dijitTreeExpandLeaf dijitTreeChildrenNo\" waiRole=\"presentation\"\n\t\tdojoAttachPoint=\"rowNode\"\n\t\t><span dojoAttachPoint=\"expandoNode\" class=\"dijitTreeExpando\" waiRole=\"presentation\"\n\t\t></span\n\t\t><span dojoAttachPoint=\"expandoNodeText\" class=\"dijitExpandoText\" waiRole=\"presentation\"\n\t\t></span\n\t\t>\n\t\t<div dojoAttachPoint=\"contentNode\" class=\"dijitTreeContent\" waiRole=\"presentation\">\n\t\t\t<div dojoAttachPoint=\"iconNode\" class=\"dijitInline dijitTreeIcon\" waiRole=\"presentation\"></div>\n\t\t\t<span dojoAttachPoint=\"labelNode\" class=\"dijitTreeLabel\" wairole=\"treeitem\" tabindex=\"0\"></span>\n\t\t</div>\n\t</div>\n</div>\n",
|
||||
|
||||
isExpandable: true,
|
||||
|
||||
isTree: true,
|
||||
|
||||
// persist: Boolean
|
||||
// enables/disables use of cookies for state saving.
|
||||
persist: true,
|
||||
|
||||
// dndController: String
|
||||
// class name to use as as the dnd controller
|
||||
dndController: null,
|
||||
|
||||
//parameters to pull off of the tree and pass on to the dndController as its params
|
||||
dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance"],
|
||||
|
||||
//declare the above items so they can be pulled from the tree's markup
|
||||
onDndDrop:null,
|
||||
itemCreator:null,
|
||||
onDndCancel:null,
|
||||
checkAcceptance:null,
|
||||
checkItemAcceptance:null,
|
||||
|
||||
_publish: function(/*String*/ topicName, /*Object*/ message){
|
||||
// summary:
|
||||
// Publish a message for this widget/topic
|
||||
dojo.publish(this.id, [dojo.mixin({tree: this, event: topicName}, message||{})]);
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.tree = this;
|
||||
this.lastFocused = this.labelNode;
|
||||
|
||||
this._itemNodeMap={};
|
||||
|
||||
this._hideRoot = !this.label;
|
||||
|
||||
if(!this.store.getFeatures()['dojo.data.api.Identity']){
|
||||
throw new Error("dijit.tree requires access to a store supporting the dojo.data Identity api");
|
||||
}
|
||||
|
||||
if(!this.cookieName){
|
||||
this.cookieName = this.id + "SaveStateCookie";
|
||||
}
|
||||
|
||||
// if the store supports Notification, subscribe to the notification events
|
||||
if(this.store.getFeatures()['dojo.data.api.Notification']){
|
||||
this.connect(this.store, "onNew", "_onNewItem");
|
||||
this.connect(this.store, "onDelete", "_onDeleteItem");
|
||||
this.connect(this.store, "onSet", "_onSetItem");
|
||||
}
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
// load in which nodes should be opened automatically
|
||||
if(this.persist){
|
||||
var cookie = dojo.cookie(this.cookieName);
|
||||
this._openedItemIds = {};
|
||||
if(cookie){
|
||||
dojo.forEach(cookie.split(','), function(item){
|
||||
this._openedItemIds[item] = true;
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
|
||||
// make template for container node (we will clone this and insert it into
|
||||
// any nodes that have children)
|
||||
var div = document.createElement('div');
|
||||
div.style.display = 'none';
|
||||
div.className = "dijitTreeContainer";
|
||||
dijit.setWaiRole(div, "presentation");
|
||||
this.containerNodeTemplate = div;
|
||||
|
||||
if(this._hideRoot){
|
||||
this.rowNode.style.display="none";
|
||||
}
|
||||
|
||||
this.inherited("postCreate", arguments);
|
||||
|
||||
// load top level children
|
||||
this._expandNode(this);
|
||||
|
||||
if(this.dndController){
|
||||
if(dojo.isString(this.dndController)){
|
||||
this.dndController= dojo.getObject(this.dndController);
|
||||
}
|
||||
var params={};
|
||||
for (var i=0; i<this.dndParams.length;i++){
|
||||
if(this[this.dndParams[i]]){
|
||||
params[this.dndParams[i]]=this[this.dndParams[i]];
|
||||
}
|
||||
}
|
||||
this.dndController= new this.dndController(this, params);
|
||||
}
|
||||
|
||||
this.connect(this.domNode,
|
||||
dojo.isIE ? "onactivate" : "onfocus",
|
||||
"_onTreeFocus");
|
||||
},
|
||||
|
||||
////////////// Data store related functions //////////////////////
|
||||
|
||||
mayHaveChildren: function(/*dojo.data.Item*/ item){
|
||||
// summary
|
||||
// User overridable function to tell if an item has or may have children.
|
||||
// Controls whether or not +/- expando icon is shown.
|
||||
// (For efficiency reasons we may not want to check if an element has
|
||||
// children until user clicks the expando node)
|
||||
|
||||
return dojo.some(this.childrenAttr, function(attr){
|
||||
return this.store.hasAttribute(item, attr);
|
||||
}, this);
|
||||
},
|
||||
|
||||
getItemChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete){
|
||||
// summary
|
||||
// User overridable function that return array of child items of given parent item,
|
||||
// or if parentItem==null then return top items in tree
|
||||
var store = this.store;
|
||||
if(parentItem == null){
|
||||
// get top level nodes
|
||||
store.fetch({ query: this.query, onComplete: onComplete});
|
||||
}else{
|
||||
// get children of specified node
|
||||
var childItems = [];
|
||||
for (var i=0; i<this.childrenAttr.length; i++){
|
||||
childItems= childItems.concat(store.getValues(parentItem, this.childrenAttr[i]));
|
||||
}
|
||||
// count how many items need to be loaded
|
||||
var _waitCount = 0;
|
||||
dojo.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
|
||||
|
||||
if(_waitCount == 0){
|
||||
// all items are already loaded. proceed..
|
||||
onComplete(childItems);
|
||||
}else{
|
||||
// still waiting for some or all of the items to load
|
||||
function onItem(item){
|
||||
if(--_waitCount == 0){
|
||||
// all nodes have been loaded, send them to the tree
|
||||
onComplete(childItems);
|
||||
}
|
||||
}
|
||||
dojo.forEach(childItems, function(item){
|
||||
if(!store.isItemLoaded(item)){
|
||||
store.loadItem({item: item, onItem: onItem});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getItemParentIdentity: function(/*dojo.data.Item*/ item, /*Object*/ parentInfo){
|
||||
// summary
|
||||
// User overridable function, to return id of parent (or null if top level).
|
||||
// It's called with args from dojo.store.onNew
|
||||
return this.store.getIdentity(parentInfo.item); // String
|
||||
},
|
||||
|
||||
getLabel: function(/*dojo.data.Item*/ item){
|
||||
// summary: user overridable function to get the label for a tree node (given the item)
|
||||
return this.store.getLabel(item); // String
|
||||
},
|
||||
|
||||
getIconClass: function(/*dojo.data.Item*/ item){
|
||||
// summary: user overridable function to return CSS class name to display icon
|
||||
},
|
||||
|
||||
getLabelClass: function(/*dojo.data.Item*/ item){
|
||||
// summary: user overridable function to return CSS class name to display label
|
||||
},
|
||||
|
||||
_onLoadAllItems: function(/*_TreeNode*/ node, /*dojo.data.Item[]*/ items){
|
||||
// sumary: callback when all the children of a given node have been loaded
|
||||
var childParams=dojo.map(items, function(item){
|
||||
return {
|
||||
item: item,
|
||||
isExpandable: this.mayHaveChildren(item)
|
||||
};
|
||||
}, this);
|
||||
|
||||
dojo.mixin(this._itemNodeMap,node._setChildren(childParams));
|
||||
|
||||
this._expandNode(node);
|
||||
},
|
||||
|
||||
/////////// Keyboard and Mouse handlers ////////////////////
|
||||
|
||||
_onKeyPress: function(/*Event*/ e){
|
||||
// summary: translates keypress events into commands for the controller
|
||||
if(e.altKey){ return; }
|
||||
var treeNode = dijit.getEnclosingWidget(e.target);
|
||||
if(!treeNode){ return; }
|
||||
|
||||
// Note: On IE e.keyCode is not 0 for printables so check e.charCode.
|
||||
// In dojo charCode is universally 0 for non-printables.
|
||||
if(e.charCode){ // handle printables (letter navigation)
|
||||
// Check for key navigation.
|
||||
var navKey = e.charCode;
|
||||
if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){
|
||||
navKey = (String.fromCharCode(navKey)).toLowerCase();
|
||||
this._onLetterKeyNav( { node: treeNode, key: navKey } );
|
||||
dojo.stopEvent(e);
|
||||
}
|
||||
}else{ // handle non-printables (arrow keys)
|
||||
var map = this._keyHandlerMap;
|
||||
if(!map){
|
||||
// setup table mapping keys to events
|
||||
map = {};
|
||||
map[dojo.keys.ENTER]="_onEnterKey";
|
||||
map[dojo.keys.LEFT_ARROW]="_onLeftArrow";
|
||||
map[dojo.keys.RIGHT_ARROW]="_onRightArrow";
|
||||
map[dojo.keys.UP_ARROW]="_onUpArrow";
|
||||
map[dojo.keys.DOWN_ARROW]="_onDownArrow";
|
||||
map[dojo.keys.HOME]="_onHomeKey";
|
||||
map[dojo.keys.END]="_onEndKey";
|
||||
this._keyHandlerMap = map;
|
||||
}
|
||||
if(this._keyHandlerMap[e.keyCode]){
|
||||
this[this._keyHandlerMap[e.keyCode]]( { node: treeNode, item: treeNode.item } );
|
||||
dojo.stopEvent(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onEnterKey: function(/*Object*/ message){
|
||||
this._publish("execute", { item: message.item, node: message.node} );
|
||||
this.onClick(message.item, message.node);
|
||||
},
|
||||
|
||||
_onDownArrow: function(/*Object*/ message){
|
||||
// summary: down arrow pressed; get next visible node, set focus there
|
||||
var returnNode = this._navToNextNode(message.node);
|
||||
if(returnNode && returnNode.isTreeNode){
|
||||
returnNode.tree.focusNode(returnNode);
|
||||
return returnNode;
|
||||
}
|
||||
},
|
||||
|
||||
_onUpArrow: function(/*Object*/ message){
|
||||
// summary: up arrow pressed; move to previous visible node
|
||||
|
||||
var nodeWidget = message.node;
|
||||
var returnWidget = nodeWidget;
|
||||
|
||||
// if younger siblings
|
||||
var previousSibling = nodeWidget.getPreviousSibling();
|
||||
if(previousSibling){
|
||||
nodeWidget = previousSibling;
|
||||
// if the previous nodeWidget is expanded, dive in deep
|
||||
while(nodeWidget.isExpandable && nodeWidget.isExpanded && nodeWidget.hasChildren()){
|
||||
returnWidget = nodeWidget;
|
||||
// move to the last child
|
||||
var children = nodeWidget.getChildren();
|
||||
nodeWidget = children[children.length-1];
|
||||
}
|
||||
}else{
|
||||
// if this is the first child, return the parent
|
||||
// unless the parent is the root of a tree with a hidden root
|
||||
var parent = nodeWidget.getParent();
|
||||
if(!(this._hideRoot && parent === this)){
|
||||
nodeWidget = parent;
|
||||
}
|
||||
}
|
||||
|
||||
if(nodeWidget && nodeWidget.isTreeNode){
|
||||
returnWidget = nodeWidget;
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
_onRightArrow: function(/*Object*/ message){
|
||||
// summary: right arrow pressed; go to child node
|
||||
var nodeWidget = message.node;
|
||||
var returnWidget = nodeWidget;
|
||||
|
||||
// if not expanded, expand, else move to 1st child
|
||||
if(nodeWidget.isExpandable && !nodeWidget.isExpanded){
|
||||
this._expandNode(nodeWidget);
|
||||
}else if(nodeWidget.hasChildren()){
|
||||
nodeWidget = nodeWidget.getChildren()[0];
|
||||
}
|
||||
|
||||
if(nodeWidget && nodeWidget.isTreeNode){
|
||||
returnWidget = nodeWidget;
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
_onLeftArrow: function(/*Object*/ message){
|
||||
// summary: left arrow pressed; go to parent
|
||||
|
||||
var node = message.node;
|
||||
var returnWidget = node;
|
||||
|
||||
// if not collapsed, collapse, else move to parent
|
||||
if(node.isExpandable && node.isExpanded){
|
||||
this._collapseNode(node);
|
||||
}else{
|
||||
node = node.getParent();
|
||||
}
|
||||
if(node && node.isTreeNode){
|
||||
returnWidget = node;
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
_onHomeKey: function(){
|
||||
// summary: home pressed; get first visible node, set focus there
|
||||
var returnNode = this._navToRootOrFirstNode();
|
||||
if(returnNode){
|
||||
returnNode.tree.focusNode(returnNode);
|
||||
return returnNode;
|
||||
}
|
||||
},
|
||||
|
||||
_onEndKey: function(/*Object*/ message){
|
||||
// summary: end pressed; go to last visible node
|
||||
|
||||
var returnWidget = message.node.tree;
|
||||
|
||||
var lastChild = returnWidget;
|
||||
while(lastChild.isExpanded){
|
||||
var c = lastChild.getChildren();
|
||||
lastChild = c[c.length - 1];
|
||||
if(lastChild.isTreeNode){
|
||||
returnWidget = lastChild;
|
||||
}
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
_onLetterKeyNav: function(message){
|
||||
// summary: letter key pressed; search for node starting with first char = key
|
||||
var node = startNode = message.node;
|
||||
var key = message.key;
|
||||
do{
|
||||
node = this._navToNextNode(node);
|
||||
//check for last node, jump to first node if necessary
|
||||
if(!node){
|
||||
node = this._navToRootOrFirstNode();
|
||||
}
|
||||
}while(node !== startNode && (node.label.charAt(0).toLowerCase() != key));
|
||||
if(node && node.isTreeNode){
|
||||
// no need to set focus if back where we started
|
||||
if(node !== startNode){
|
||||
node.tree.focusNode(node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
},
|
||||
|
||||
_onClick: function(/*Event*/ e){
|
||||
// summary: translates click events into commands for the controller to process
|
||||
var domElement = e.target;
|
||||
|
||||
// find node
|
||||
var nodeWidget = dijit.getEnclosingWidget(domElement);
|
||||
if(!nodeWidget || !nodeWidget.isTreeNode){
|
||||
return;
|
||||
}
|
||||
|
||||
if(domElement == nodeWidget.expandoNode ||
|
||||
domElement == nodeWidget.expandoNodeText){
|
||||
// expando node was clicked
|
||||
if(nodeWidget.isExpandable){
|
||||
this._onExpandoClick({node:nodeWidget});
|
||||
}
|
||||
}else{
|
||||
this._publish("execute", { item: nodeWidget.item, node: nodeWidget} );
|
||||
this.onClick(nodeWidget.item, nodeWidget);
|
||||
this.focusNode(nodeWidget);
|
||||
}
|
||||
dojo.stopEvent(e);
|
||||
},
|
||||
|
||||
_onExpandoClick: function(/*Object*/ message){
|
||||
// summary: user clicked the +/- icon; expand or collapse my children.
|
||||
var node = message.node;
|
||||
if(node.isExpanded){
|
||||
this._collapseNode(node);
|
||||
}else{
|
||||
this._expandNode(node);
|
||||
}
|
||||
},
|
||||
|
||||
onClick: function(/* dojo.data */ item, /*TreeNode*/ node){
|
||||
// summary: user overridable function for executing a tree item
|
||||
},
|
||||
|
||||
_navToNextNode: function(node){
|
||||
// summary: get next visible node
|
||||
var returnNode;
|
||||
// if this is an expanded node, get the first child
|
||||
if(node.isExpandable && node.isExpanded && node.hasChildren()){
|
||||
returnNode = node.getChildren()[0];
|
||||
}else{
|
||||
// find a parent node with a sibling
|
||||
while(node && node.isTreeNode){
|
||||
returnNode = node.getNextSibling();
|
||||
if(returnNode){
|
||||
break;
|
||||
}
|
||||
node = node.getParent();
|
||||
}
|
||||
}
|
||||
return returnNode;
|
||||
},
|
||||
|
||||
_navToRootOrFirstNode: function(){
|
||||
// summary: get first visible node
|
||||
if(!this._hideRoot){
|
||||
return this;
|
||||
}else{
|
||||
var returnNode = this.getChildren()[0];
|
||||
if(returnNode && returnNode.isTreeNode){
|
||||
return returnNode;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_collapseNode: function(/*_TreeNode*/ node){
|
||||
// summary: called when the user has requested to collapse the node
|
||||
|
||||
if(node.isExpandable){
|
||||
if(node.state == "LOADING"){
|
||||
// ignore clicks while we are in the process of loading data
|
||||
return;
|
||||
}
|
||||
if(this.lastFocused){
|
||||
// are we collapsing a descendant with focus?
|
||||
if(dojo.isDescendant(this.lastFocused.domNode, node.domNode)){
|
||||
this.focusNode(node);
|
||||
}else{
|
||||
// clicking the expando node might have erased focus from
|
||||
// the current item; restore it
|
||||
this.focusNode(this.lastFocused);
|
||||
}
|
||||
}
|
||||
node.collapse();
|
||||
if(this.persist && node.item){
|
||||
delete this._openedItemIds[this.store.getIdentity(node.item)];
|
||||
this._saveState();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_expandNode: function(/*_TreeNode*/ node){
|
||||
// summary: called when the user has requested to expand the node
|
||||
|
||||
// clicking the expando node might have erased focus from the current item; restore it
|
||||
var t = node.tree;
|
||||
if(t.lastFocused){ t.focusNode(t.lastFocused); }
|
||||
|
||||
if(!node.isExpandable){
|
||||
return;
|
||||
}
|
||||
|
||||
var store = this.store;
|
||||
var getValue = this.store.getValue;
|
||||
|
||||
switch(node.state){
|
||||
case "LOADING":
|
||||
// ignore clicks while we are in the process of loading data
|
||||
return;
|
||||
|
||||
case "UNCHECKED":
|
||||
// need to load all the children, and then expand
|
||||
node.markProcessing();
|
||||
var _this = this;
|
||||
function onComplete(childItems){
|
||||
node.unmarkProcessing();
|
||||
_this._onLoadAllItems(node, childItems);
|
||||
}
|
||||
this.getItemChildren(node.item, onComplete);
|
||||
break;
|
||||
|
||||
default:
|
||||
// data is already loaded; just proceed
|
||||
if(node.expand){ // top level Tree doesn't have expand() method
|
||||
node.expand();
|
||||
if(this.persist && node.item){
|
||||
this._openedItemIds[this.store.getIdentity(node.item)] = true;
|
||||
this._saveState();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
////////////////// Miscellaneous functions ////////////////
|
||||
|
||||
blurNode: function(){
|
||||
// summary
|
||||
// Removes focus from the currently focused node (which must be visible).
|
||||
// Usually not called directly (just call focusNode() on another node instead)
|
||||
var node = this.lastFocused;
|
||||
if(!node){ return; }
|
||||
var labelNode = node.labelNode;
|
||||
dojo.removeClass(labelNode, "dijitTreeLabelFocused");
|
||||
labelNode.setAttribute("tabIndex", "-1");
|
||||
this.lastFocused = null;
|
||||
},
|
||||
|
||||
focusNode: function(/* _tree.Node */ node){
|
||||
// summary
|
||||
// Focus on the specified node (which must be visible)
|
||||
|
||||
// set focus so that the label will be voiced using screen readers
|
||||
node.labelNode.focus();
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
// summary:
|
||||
// We've moved away from the whole tree. The currently "focused" node
|
||||
// (see focusNode above) should remain as the lastFocused node so we can
|
||||
// tab back into the tree. Just change CSS to get rid of the dotted border
|
||||
// until that time
|
||||
if(this.lastFocused){
|
||||
var labelNode = this.lastFocused.labelNode;
|
||||
dojo.removeClass(labelNode, "dijitTreeLabelFocused");
|
||||
}
|
||||
},
|
||||
|
||||
_onTreeFocus: function(evt){
|
||||
var node = dijit.getEnclosingWidget(evt.target);
|
||||
if(node != this.lastFocused){
|
||||
this.blurNode();
|
||||
}
|
||||
var labelNode = node.labelNode;
|
||||
// set tabIndex so that the tab key can find this node
|
||||
labelNode.setAttribute("tabIndex", "0");
|
||||
dojo.addClass(labelNode, "dijitTreeLabelFocused");
|
||||
this.lastFocused = node;
|
||||
},
|
||||
|
||||
//////////////// Events from data store //////////////////////////
|
||||
|
||||
|
||||
_onNewItem: function(/*Object*/ item, parentInfo){
|
||||
//summary: callback when new item has been added to the store.
|
||||
|
||||
var loadNewItem; // should new item be displayed in tree?
|
||||
|
||||
if(parentInfo){
|
||||
var parent = this._itemNodeMap[this.getItemParentIdentity(item, parentInfo)];
|
||||
|
||||
// If new item's parent item not in tree view yet, can safely ignore.
|
||||
// Also, if a query of specified parent wouldn't return this item, then ignore.
|
||||
if(!parent ||
|
||||
dojo.indexOf(this.childrenAttr, parentInfo.attribute) == -1){
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var childParams = {
|
||||
item: item,
|
||||
isExpandable: this.mayHaveChildren(item)
|
||||
};
|
||||
if(parent){
|
||||
if(!parent.isExpandable){
|
||||
parent.makeExpandable();
|
||||
}
|
||||
if(parent.state=="LOADED" || parent.isExpanded){
|
||||
var childrenMap=parent._addChildren([childParams]);
|
||||
}
|
||||
}else{
|
||||
// top level node
|
||||
var childrenMap=this._addChildren([childParams]);
|
||||
}
|
||||
|
||||
if(childrenMap){
|
||||
dojo.mixin(this._itemNodeMap, childrenMap);
|
||||
//this._itemNodeMap[this.store.getIdentity(item)]=child;
|
||||
}
|
||||
},
|
||||
|
||||
_onDeleteItem: function(/*Object*/ item){
|
||||
//summary: delete event from the store
|
||||
//since the object has just been deleted, we need to
|
||||
//use the name directly
|
||||
var identity = this.store.getIdentity(item);
|
||||
var node = this._itemNodeMap[identity];
|
||||
|
||||
if(node){
|
||||
var parent = node.getParent();
|
||||
parent.deleteNode(node);
|
||||
this._itemNodeMap[identity]=null;
|
||||
}
|
||||
},
|
||||
|
||||
_onSetItem: function(/*Object*/ item){
|
||||
//summary: set data event on an item in the store
|
||||
var identity = this.store.getIdentity(item);
|
||||
node = this._itemNodeMap[identity];
|
||||
|
||||
if(node){
|
||||
node.setLabelNode(this.getLabel(item));
|
||||
node._updateItemClasses(item);
|
||||
}
|
||||
},
|
||||
|
||||
_saveState: function(){
|
||||
//summary: create and save a cookie with the currently expanded nodes identifiers
|
||||
if(!this.persist){
|
||||
return;
|
||||
}
|
||||
var ary = [];
|
||||
for(var id in this._openedItemIds){
|
||||
ary.push(id);
|
||||
}
|
||||
dojo.cookie(this.cookieName, ary.join(","));
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._Calendar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._Calendar"] = true;
|
||||
dojo.provide("dijit._Calendar");
|
||||
|
||||
dojo.require("dojo.cldr.supplemental");
|
||||
dojo.require("dojo.date");
|
||||
dojo.require("dojo.date.locale");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare(
|
||||
"dijit._Calendar",
|
||||
[dijit._Widget, dijit._Templated],
|
||||
{
|
||||
/*
|
||||
summary:
|
||||
A simple GUI for choosing a date in the context of a monthly calendar.
|
||||
|
||||
description:
|
||||
This widget is used internally by other widgets and is not accessible
|
||||
as a standalone widget.
|
||||
This widget can't be used in a form because it doesn't serialize the date to an
|
||||
<input> field. For a form element, use DateTextBox instead.
|
||||
|
||||
Note that the parser takes all dates attributes passed in the `RFC 3339` format:
|
||||
http://www.faqs.org/rfcs/rfc3339.html (2005-06-30T08:05:00-07:00)
|
||||
so that they are serializable and locale-independent.
|
||||
|
||||
usage:
|
||||
var calendar = new dijit._Calendar({}, dojo.byId("calendarNode"));
|
||||
-or-
|
||||
<div dojoType="dijit._Calendar"></div>
|
||||
*/
|
||||
templateString:"<table cellspacing=\"0\" cellpadding=\"0\" class=\"dijitCalendarContainer\">\n\t<thead>\n\t\t<tr class=\"dijitReset dijitCalendarMonthContainer\" valign=\"top\">\n\t\t\t<th class='dijitReset' dojoAttachPoint=\"decrementMonth\">\n\t\t\t\t<span class=\"dijitInline dijitCalendarIncrementControl dijitCalendarDecrease\"><span dojoAttachPoint=\"decreaseArrowNode\" class=\"dijitA11ySideArrow dijitCalendarIncrementControl dijitCalendarDecreaseInner\">-</span></span>\n\t\t\t</th>\n\t\t\t<th class='dijitReset' colspan=\"5\">\n\t\t\t\t<div dojoAttachPoint=\"monthLabelSpacer\" class=\"dijitCalendarMonthLabelSpacer\"></div>\n\t\t\t\t<div dojoAttachPoint=\"monthLabelNode\" class=\"dijitCalendarMonth\"></div>\n\t\t\t</th>\n\t\t\t<th class='dijitReset' dojoAttachPoint=\"incrementMonth\">\n\t\t\t\t<div class=\"dijitInline dijitCalendarIncrementControl dijitCalendarIncrease\"><span dojoAttachPoint=\"increaseArrowNode\" class=\"dijitA11ySideArrow dijitCalendarIncrementControl dijitCalendarIncreaseInner\">+</span></div>\n\t\t\t</th>\n\t\t</tr>\n\t\t<tr>\n\t\t\t<th class=\"dijitReset dijitCalendarDayLabelTemplate\"><span class=\"dijitCalendarDayLabel\"></span></th>\n\t\t</tr>\n\t</thead>\n\t<tbody dojoAttachEvent=\"onclick: _onDayClick\" class=\"dijitReset dijitCalendarBodyContainer\">\n\t\t<tr class=\"dijitReset dijitCalendarWeekTemplate\">\n\t\t\t<td class=\"dijitReset dijitCalendarDateTemplate\"><span class=\"dijitCalendarDateLabel\"></span></td>\n\t\t</tr>\n\t</tbody>\n\t<tfoot class=\"dijitReset dijitCalendarYearContainer\">\n\t\t<tr>\n\t\t\t<td class='dijitReset' valign=\"top\" colspan=\"7\">\n\t\t\t\t<h3 class=\"dijitCalendarYearLabel\">\n\t\t\t\t\t<span dojoAttachPoint=\"previousYearLabelNode\" class=\"dijitInline dijitCalendarPreviousYear\"></span>\n\t\t\t\t\t<span dojoAttachPoint=\"currentYearLabelNode\" class=\"dijitInline dijitCalendarSelectedYear\"></span>\n\t\t\t\t\t<span dojoAttachPoint=\"nextYearLabelNode\" class=\"dijitInline dijitCalendarNextYear\"></span>\n\t\t\t\t</h3>\n\t\t\t</td>\n\t\t</tr>\n\t</tfoot>\n</table>\t\n",
|
||||
|
||||
// value: Date
|
||||
// the currently selected Date
|
||||
value: new Date(),
|
||||
|
||||
// dayWidth: String
|
||||
// How to represent the days of the week in the calendar header. See dojo.date.locale
|
||||
dayWidth: "narrow",
|
||||
|
||||
setValue: function(/*Date*/ value){
|
||||
// summary: set the current date and update the UI. If the date is disabled, the selection will
|
||||
// not change, but the display will change to the corresponding month.
|
||||
if(!this.value || dojo.date.compare(value, this.value)){
|
||||
value = new Date(value);
|
||||
this.displayMonth = new Date(value);
|
||||
if(!this.isDisabledDate(value, this.lang)){
|
||||
this.value = value;
|
||||
this.value.setHours(0,0,0,0);
|
||||
this.onChange(this.value);
|
||||
}
|
||||
this._populateGrid();
|
||||
}
|
||||
},
|
||||
|
||||
_setText: function(node, text){
|
||||
while(node.firstChild){
|
||||
node.removeChild(node.firstChild);
|
||||
}
|
||||
node.appendChild(document.createTextNode(text));
|
||||
},
|
||||
|
||||
_populateGrid: function(){
|
||||
var month = this.displayMonth;
|
||||
month.setDate(1);
|
||||
var firstDay = month.getDay();
|
||||
var daysInMonth = dojo.date.getDaysInMonth(month);
|
||||
var daysInPreviousMonth = dojo.date.getDaysInMonth(dojo.date.add(month, "month", -1));
|
||||
var today = new Date();
|
||||
var selected = this.value;
|
||||
|
||||
var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
|
||||
if(dayOffset > firstDay){ dayOffset -= 7; }
|
||||
|
||||
// Iterate through dates in the calendar and fill in date numbers and style info
|
||||
dojo.query(".dijitCalendarDateTemplate", this.domNode).forEach(function(template, i){
|
||||
i += dayOffset;
|
||||
var date = new Date(month);
|
||||
var number, clazz = "dijitCalendar", adj = 0;
|
||||
|
||||
if(i < firstDay){
|
||||
number = daysInPreviousMonth - firstDay + i + 1;
|
||||
adj = -1;
|
||||
clazz += "Previous";
|
||||
}else if(i >= (firstDay + daysInMonth)){
|
||||
number = i - firstDay - daysInMonth + 1;
|
||||
adj = 1;
|
||||
clazz += "Next";
|
||||
}else{
|
||||
number = i - firstDay + 1;
|
||||
clazz += "Current";
|
||||
}
|
||||
|
||||
if(adj){
|
||||
date = dojo.date.add(date, "month", adj);
|
||||
}
|
||||
date.setDate(number);
|
||||
|
||||
if(!dojo.date.compare(date, today, "date")){
|
||||
clazz = "dijitCalendarCurrentDate " + clazz;
|
||||
}
|
||||
|
||||
if(!dojo.date.compare(date, selected, "date")){
|
||||
clazz = "dijitCalendarSelectedDate " + clazz;
|
||||
}
|
||||
|
||||
if(this.isDisabledDate(date, this.lang)){
|
||||
clazz = "dijitCalendarDisabledDate " + clazz;
|
||||
}
|
||||
|
||||
template.className = clazz + "Month dijitCalendarDateTemplate";
|
||||
template.dijitDateValue = date.valueOf();
|
||||
var label = dojo.query(".dijitCalendarDateLabel", template)[0];
|
||||
this._setText(label, date.getDate());
|
||||
}, this);
|
||||
|
||||
// Fill in localized month name
|
||||
var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
|
||||
this._setText(this.monthLabelNode, monthNames[month.getMonth()]);
|
||||
|
||||
// Fill in localized prev/current/next years
|
||||
var y = month.getFullYear() - 1;
|
||||
dojo.forEach(["previous", "current", "next"], function(name){
|
||||
this._setText(this[name+"YearLabelNode"],
|
||||
dojo.date.locale.format(new Date(y++, 0), {selector:'year', locale:this.lang}));
|
||||
}, this);
|
||||
|
||||
// Set up repeating mouse behavior
|
||||
var _this = this;
|
||||
var typematic = function(nodeProp, dateProp, adj){
|
||||
dijit.typematic.addMouseListener(_this[nodeProp], _this, function(count){
|
||||
if(count >= 0){ _this._adjustDisplay(dateProp, adj); }
|
||||
}, 0.8, 500);
|
||||
};
|
||||
typematic("incrementMonth", "month", 1);
|
||||
typematic("decrementMonth", "month", -1);
|
||||
typematic("nextYearLabelNode", "year", 1);
|
||||
typematic("previousYearLabelNode", "year", -1);
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
dijit._Calendar.superclass.postCreate.apply(this);
|
||||
|
||||
var cloneClass = dojo.hitch(this, function(clazz, n){
|
||||
var template = dojo.query(clazz, this.domNode)[0];
|
||||
for(var i=0; i<n; i++){
|
||||
template.parentNode.appendChild(template.cloneNode(true));
|
||||
}
|
||||
});
|
||||
|
||||
// clone the day label and calendar day templates 6 times to make 7 columns
|
||||
cloneClass(".dijitCalendarDayLabelTemplate", 6);
|
||||
cloneClass(".dijitCalendarDateTemplate", 6);
|
||||
|
||||
// now make 6 week rows
|
||||
cloneClass(".dijitCalendarWeekTemplate", 5);
|
||||
|
||||
// insert localized day names in the header
|
||||
var dayNames = dojo.date.locale.getNames('days', this.dayWidth, 'standAlone', this.lang);
|
||||
var dayOffset = dojo.cldr.supplemental.getFirstDayOfWeek(this.lang);
|
||||
dojo.query(".dijitCalendarDayLabel", this.domNode).forEach(function(label, i){
|
||||
this._setText(label, dayNames[(i + dayOffset) % 7]);
|
||||
}, this);
|
||||
|
||||
// Fill in spacer element with all the month names (invisible) so that the maximum width will affect layout
|
||||
var monthNames = dojo.date.locale.getNames('months', 'wide', 'standAlone', this.lang);
|
||||
dojo.forEach(monthNames, function(name){
|
||||
var monthSpacer = dojo.doc.createElement("div");
|
||||
this._setText(monthSpacer, name);
|
||||
this.monthLabelSpacer.appendChild(monthSpacer);
|
||||
}, this);
|
||||
|
||||
this.value = null;
|
||||
this.setValue(new Date());
|
||||
},
|
||||
|
||||
_adjustDisplay: function(/*String*/part, /*int*/amount){
|
||||
this.displayMonth = dojo.date.add(this.displayMonth, part, amount);
|
||||
this._populateGrid();
|
||||
},
|
||||
|
||||
_onDayClick: function(/*Event*/evt){
|
||||
var node = evt.target;
|
||||
dojo.stopEvent(evt);
|
||||
while(!node.dijitDateValue){
|
||||
node = node.parentNode;
|
||||
}
|
||||
if(!dojo.hasClass(node, "dijitCalendarDisabledDate")){
|
||||
this.setValue(node.dijitDateValue);
|
||||
this.onValueSelected(this.value);
|
||||
}
|
||||
},
|
||||
|
||||
onValueSelected: function(/*Date*/date){
|
||||
//summary: a date cell was selected. It may be the same as the previous value.
|
||||
},
|
||||
|
||||
onChange: function(/*Date*/date){
|
||||
//summary: called only when the selected date has changed
|
||||
},
|
||||
|
||||
isDisabledDate: function(/*Date*/dateObject, /*String?*/locale){
|
||||
// summary:
|
||||
// May be overridden to disable certain dates in the calendar e.g. isDisabledDate=dojo.date.locale.isWeekend
|
||||
return false; // Boolean
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,315 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._Container"] = true;
|
||||
dojo.provide("dijit._Container");
|
||||
|
||||
dojo.declare("dijit._Contained",
|
||||
null,
|
||||
{
|
||||
// summary
|
||||
// Mixin for widgets that are children of a container widget
|
||||
|
||||
getParent: function(){
|
||||
// summary:
|
||||
// returns the parent widget of this widget, assuming the parent
|
||||
// implements dijit._Container
|
||||
for(var p=this.domNode.parentNode; p; p=p.parentNode){
|
||||
var id = p.getAttribute && p.getAttribute("widgetId");
|
||||
if(id){
|
||||
var parent = dijit.byId(id);
|
||||
return parent.isContainer ? parent : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_getSibling: function(which){
|
||||
var node = this.domNode;
|
||||
do{
|
||||
node = node[which+"Sibling"];
|
||||
}while(node && node.nodeType != 1);
|
||||
if(!node){ return null; } // null
|
||||
var id = node.getAttribute("widgetId");
|
||||
return dijit.byId(id);
|
||||
},
|
||||
|
||||
getPreviousSibling: function(){
|
||||
// summary:
|
||||
// returns null if this is the first child of the parent,
|
||||
// otherwise returns the next element sibling to the "left".
|
||||
|
||||
return this._getSibling("previous");
|
||||
},
|
||||
|
||||
getNextSibling: function(){
|
||||
// summary:
|
||||
// returns null if this is the last child of the parent,
|
||||
// otherwise returns the next element sibling to the "right".
|
||||
|
||||
return this._getSibling("next");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare("dijit._Container",
|
||||
null,
|
||||
{
|
||||
// summary
|
||||
// Mixin for widgets that contain a list of children like SplitContainer
|
||||
|
||||
isContainer: true,
|
||||
|
||||
addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
|
||||
// summary:
|
||||
// Process the given child widget, inserting it's dom node as
|
||||
// a child of our dom node
|
||||
|
||||
if(insertIndex === undefined){
|
||||
insertIndex = "last";
|
||||
}
|
||||
var refNode = this.containerNode || this.domNode;
|
||||
if(insertIndex && typeof insertIndex == "number"){
|
||||
var children = dojo.query("> [widgetid]", refNode);
|
||||
if(children && children.length >= insertIndex){
|
||||
refNode = children[insertIndex-1]; insertIndex = "after";
|
||||
}
|
||||
}
|
||||
dojo.place(widget.domNode, refNode, insertIndex);
|
||||
|
||||
// If I've been started but the child widget hasn't been started,
|
||||
// start it now. Make sure to do this after widget has been
|
||||
// inserted into the DOM tree, so it can see that it's being controlled by me,
|
||||
// so it doesn't try to size itself.
|
||||
if(this._started && !widget._started){
|
||||
widget.startup();
|
||||
}
|
||||
},
|
||||
|
||||
removeChild: function(/*Widget*/ widget){
|
||||
// summary:
|
||||
// removes the passed widget instance from this widget but does
|
||||
// not destroy it
|
||||
var node = widget.domNode;
|
||||
node.parentNode.removeChild(node); // detach but don't destroy
|
||||
},
|
||||
|
||||
_nextElement: function(node){
|
||||
do{
|
||||
node = node.nextSibling;
|
||||
}while(node && node.nodeType != 1);
|
||||
return node;
|
||||
},
|
||||
|
||||
_firstElement: function(node){
|
||||
node = node.firstChild;
|
||||
if(node && node.nodeType != 1){
|
||||
node = this._nextElement(node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
getChildren: function(){
|
||||
// summary:
|
||||
// Returns array of children widgets
|
||||
return dojo.query("> [widgetId]", this.containerNode || this.domNode).map(dijit.byNode); // Array
|
||||
},
|
||||
|
||||
hasChildren: function(){
|
||||
// summary:
|
||||
// Returns true if widget has children
|
||||
var cn = this.containerNode || this.domNode;
|
||||
return !!this._firstElement(cn); // Boolean
|
||||
},
|
||||
|
||||
_getSiblingOfChild: function(/*Widget*/ child, /*int*/ dir){
|
||||
// summary:
|
||||
// get the next or previous widget sibling of child
|
||||
// dir:
|
||||
// if 1, get the next sibling
|
||||
// if -1, get the previous sibling
|
||||
var node = child.domNode;
|
||||
var which = (dir>0 ? "nextSibling" : "previousSibling");
|
||||
do{
|
||||
node = node[which];
|
||||
}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
|
||||
return node ? dijit.byNode(node) : null;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare("dijit._KeyNavContainer",
|
||||
[dijit._Container],
|
||||
{
|
||||
|
||||
// summary:
|
||||
// A _Container with keyboard navigation of its children.
|
||||
// To use this mixin, call connectKeyNavHandlers() in
|
||||
// postCreate() and call startupKeyNavChildren() in startup().
|
||||
|
||||
/*=====
|
||||
// focusedChild: Widget
|
||||
// The currently focused child widget, or null if there isn't one
|
||||
focusedChild: null,
|
||||
=====*/
|
||||
|
||||
_keyNavCodes: {},
|
||||
|
||||
connectKeyNavHandlers: function(/*Array*/ prevKeyCodes, /*Array*/ nextKeyCodes){
|
||||
// summary:
|
||||
// Call in postCreate() to attach the keyboard handlers
|
||||
// to the container.
|
||||
// preKeyCodes: Array
|
||||
// Key codes for navigating to the previous child.
|
||||
// nextKeyCodes: Array
|
||||
// Key codes for navigating to the next child.
|
||||
|
||||
var keyCodes = this._keyNavCodes = {};
|
||||
var prev = dojo.hitch(this, this.focusPrev);
|
||||
var next = dojo.hitch(this, this.focusNext);
|
||||
dojo.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev });
|
||||
dojo.forEach(nextKeyCodes, function(code){ keyCodes[code] = next });
|
||||
this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
|
||||
if(dojo.isIE){
|
||||
this.connect(this.domNode, "onactivate", "_onContainerFocus");
|
||||
this.connect(this.domNode, "ondeactivate", "_onContainerBlur");
|
||||
}else{
|
||||
this.connect(this.domNode, "onfocus", "_onContainerFocus");
|
||||
this.connect(this.domNode, "onblur", "_onContainerBlur");
|
||||
}
|
||||
},
|
||||
|
||||
startupKeyNavChildren: function(){
|
||||
// summary:
|
||||
// Call in startup() to set child tabindexes to -1
|
||||
dojo.forEach(this.getChildren(), dojo.hitch(this, "_setTabIndexMinusOne"));
|
||||
},
|
||||
|
||||
addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
|
||||
// summary: Add a child to our _Container
|
||||
dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
|
||||
this._setTabIndexMinusOne(widget);
|
||||
},
|
||||
|
||||
focus: function(){
|
||||
// summary: Default focus() implementation: focus the first child.
|
||||
this.focusFirstChild();
|
||||
},
|
||||
|
||||
focusFirstChild: function(){
|
||||
// summary: Focus the first focusable child in the container.
|
||||
this.focusChild(this._getFirstFocusableChild());
|
||||
},
|
||||
|
||||
focusNext: function(){
|
||||
// summary: Focus the next widget or focal node (for widgets
|
||||
// with multiple focal nodes) within this container.
|
||||
if(this.focusedChild && this.focusedChild.hasNextFocalNode
|
||||
&& this.focusedChild.hasNextFocalNode()){
|
||||
this.focusedChild.focusNext();
|
||||
return;
|
||||
}
|
||||
var child = this._getNextFocusableChild(this.focusedChild, 1);
|
||||
if(child.getFocalNodes){
|
||||
this.focusChild(child, child.getFocalNodes()[0]);
|
||||
}else{
|
||||
this.focusChild(child);
|
||||
}
|
||||
},
|
||||
|
||||
focusPrev: function(){
|
||||
// summary: Focus the previous widget or focal node (for widgets
|
||||
// with multiple focal nodes) within this container.
|
||||
if(this.focusedChild && this.focusedChild.hasPrevFocalNode
|
||||
&& this.focusedChild.hasPrevFocalNode()){
|
||||
this.focusedChild.focusPrev();
|
||||
return;
|
||||
}
|
||||
var child = this._getNextFocusableChild(this.focusedChild, -1);
|
||||
if(child.getFocalNodes){
|
||||
var nodes = child.getFocalNodes();
|
||||
this.focusChild(child, nodes[nodes.length-1]);
|
||||
}else{
|
||||
this.focusChild(child);
|
||||
}
|
||||
},
|
||||
|
||||
focusChild: function(/*Widget*/ widget, /*Node?*/ node){
|
||||
// summary: Focus widget. Optionally focus 'node' within widget.
|
||||
if(widget){
|
||||
if(this.focusedChild && widget !== this.focusedChild){
|
||||
this._onChildBlur(this.focusedChild);
|
||||
}
|
||||
this.focusedChild = widget;
|
||||
if(node && widget.focusFocalNode){
|
||||
widget.focusFocalNode(node);
|
||||
}else{
|
||||
widget.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_setTabIndexMinusOne: function(/*Widget*/ widget){
|
||||
if(widget.getFocalNodes){
|
||||
dojo.forEach(widget.getFocalNodes(), function(node){
|
||||
node.setAttribute("tabIndex", -1);
|
||||
});
|
||||
}else{
|
||||
(widget.focusNode || widget.domNode).setAttribute("tabIndex", -1);
|
||||
}
|
||||
},
|
||||
|
||||
_onContainerFocus: function(evt){
|
||||
this.domNode.setAttribute("tabIndex", -1);
|
||||
if(evt.target === this.domNode){
|
||||
this.focusFirstChild();
|
||||
}else{
|
||||
var widget = dijit.getEnclosingWidget(evt.target);
|
||||
if(widget && widget.isFocusable()){
|
||||
this.focusedChild = widget;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onContainerBlur: function(evt){
|
||||
if(this.tabIndex){
|
||||
this.domNode.setAttribute("tabIndex", this.tabIndex);
|
||||
}
|
||||
},
|
||||
|
||||
_onContainerKeypress: function(evt){
|
||||
if(evt.ctrlKey || evt.altKey){ return; }
|
||||
var func = this._keyNavCodes[evt.keyCode];
|
||||
if(func){
|
||||
func();
|
||||
dojo.stopEvent(evt);
|
||||
}
|
||||
},
|
||||
|
||||
_onChildBlur: function(/*Widget*/ widget){
|
||||
// summary:
|
||||
// Called when focus leaves a child widget to go
|
||||
// to a sibling widget.
|
||||
},
|
||||
|
||||
_getFirstFocusableChild: function(){
|
||||
return this._getNextFocusableChild(null, 1);
|
||||
},
|
||||
|
||||
_getNextFocusableChild: function(child, dir){
|
||||
if(child){
|
||||
child = this._getSiblingOfChild(child, dir);
|
||||
}
|
||||
var children = this.getChildren();
|
||||
for(var i=0; i < children.length; i++){
|
||||
if(!child){
|
||||
child = children[(dir>0) ? 0 : (children.length-1)];
|
||||
}
|
||||
if(child.isFocusable()){
|
||||
return child;
|
||||
}
|
||||
child = this._getSiblingOfChild(child, dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,326 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._Templated"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._Templated"] = true;
|
||||
dojo.provide("dijit._Templated");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
|
||||
dojo.require("dojo.string");
|
||||
dojo.require("dojo.parser");
|
||||
|
||||
dojo.declare("dijit._Templated",
|
||||
null,
|
||||
{
|
||||
// summary:
|
||||
// mixin for widgets that are instantiated from a template
|
||||
|
||||
// templateNode: DomNode
|
||||
// a node that represents the widget template. Pre-empts both templateString and templatePath.
|
||||
templateNode: null,
|
||||
|
||||
// templateString String:
|
||||
// a string that represents the widget template. Pre-empts the
|
||||
// templatePath. In builds that have their strings "interned", the
|
||||
// templatePath is converted to an inline templateString, thereby
|
||||
// preventing a synchronous network call.
|
||||
templateString: null,
|
||||
|
||||
// templatePath: String
|
||||
// Path to template (HTML file) for this widget
|
||||
templatePath: null,
|
||||
|
||||
// widgetsInTemplate Boolean:
|
||||
// should we parse the template to find widgets that might be
|
||||
// declared in markup inside it? false by default.
|
||||
widgetsInTemplate: false,
|
||||
|
||||
// containerNode DomNode:
|
||||
// holds child elements. "containerNode" is generally set via a
|
||||
// dojoAttachPoint assignment and it designates where children of
|
||||
// the src dom node will be placed
|
||||
containerNode: null,
|
||||
|
||||
// skipNodeCache Boolean:
|
||||
// if using a cached widget template node poses issues for a
|
||||
// particular widget class, it can set this property to ensure
|
||||
// that its template is always re-built from a string
|
||||
_skipNodeCache: false,
|
||||
|
||||
// method over-ride
|
||||
buildRendering: function(){
|
||||
// summary:
|
||||
// Construct the UI for this widget from a template, setting this.domNode.
|
||||
|
||||
// Lookup cached version of template, and download to cache if it
|
||||
// isn't there already. Returns either a DomNode or a string, depending on
|
||||
// whether or not the template contains ${foo} replacement parameters.
|
||||
var cached = dijit._Templated.getCachedTemplate(this.templatePath, this.templateString, this._skipNodeCache);
|
||||
|
||||
var node;
|
||||
if(dojo.isString(cached)){
|
||||
var className = this.declaredClass, _this = this;
|
||||
// Cache contains a string because we need to do property replacement
|
||||
// do the property replacement
|
||||
var tstr = dojo.string.substitute(cached, this, function(value, key){
|
||||
if(key.charAt(0) == '!'){ value = _this[key.substr(1)]; }
|
||||
if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
|
||||
if(!value){ return ""; }
|
||||
|
||||
// Substitution keys beginning with ! will skip the transform step,
|
||||
// in case a user wishes to insert unescaped markup, e.g. ${!foo}
|
||||
return key.charAt(0) == "!" ? value :
|
||||
// Safer substitution, see heading "Attribute values" in
|
||||
// http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
|
||||
value.toString().replace(/"/g,"""); //TODO: add &? use encodeXML method?
|
||||
}, this);
|
||||
|
||||
node = dijit._Templated._createNodesFromText(tstr)[0];
|
||||
}else{
|
||||
// if it's a node, all we have to do is clone it
|
||||
node = cached.cloneNode(true);
|
||||
}
|
||||
|
||||
// recurse through the node, looking for, and attaching to, our
|
||||
// attachment points which should be defined on the template node.
|
||||
this._attachTemplateNodes(node);
|
||||
|
||||
var source = this.srcNodeRef;
|
||||
if(source && source.parentNode){
|
||||
source.parentNode.replaceChild(node, source);
|
||||
}
|
||||
|
||||
this.domNode = node;
|
||||
if(this.widgetsInTemplate){
|
||||
var childWidgets = dojo.parser.parse(node);
|
||||
this._attachTemplateNodes(childWidgets, function(n,p){
|
||||
return n[p];
|
||||
});
|
||||
}
|
||||
|
||||
this._fillContent(source);
|
||||
},
|
||||
|
||||
_fillContent: function(/*DomNode*/ source){
|
||||
// summary:
|
||||
// relocate source contents to templated container node
|
||||
// this.containerNode must be able to receive children, or exceptions will be thrown
|
||||
var dest = this.containerNode;
|
||||
if(source && dest){
|
||||
while(source.hasChildNodes()){
|
||||
dest.appendChild(source.firstChild);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_attachTemplateNodes: function(rootNode, getAttrFunc){
|
||||
// summary:
|
||||
// map widget properties and functions to the handlers specified in
|
||||
// the dom node and it's descendants. This function iterates over all
|
||||
// nodes and looks for these properties:
|
||||
// * dojoAttachPoint
|
||||
// * dojoAttachEvent
|
||||
// * waiRole
|
||||
// * waiState
|
||||
// rootNode: DomNode|Array[Widgets]
|
||||
// the node to search for properties. All children will be searched.
|
||||
// getAttrFunc: function?
|
||||
// a function which will be used to obtain property for a given
|
||||
// DomNode/Widget
|
||||
|
||||
getAttrFunc = getAttrFunc || function(n,p){ return n.getAttribute(p); };
|
||||
|
||||
var nodes = dojo.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
|
||||
var x=dojo.isArray(rootNode)?0:-1;
|
||||
for(; x<nodes.length; x++){
|
||||
var baseNode = (x == -1) ? rootNode : nodes[x];
|
||||
if(this.widgetsInTemplate && getAttrFunc(baseNode,'dojoType')){
|
||||
continue;
|
||||
}
|
||||
// Process dojoAttachPoint
|
||||
var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint");
|
||||
if(attachPoint){
|
||||
var point, points = attachPoint.split(/\s*,\s*/);
|
||||
while(point=points.shift()){
|
||||
if(dojo.isArray(this[point])){
|
||||
this[point].push(baseNode);
|
||||
}else{
|
||||
this[point]=baseNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Process dojoAttachEvent
|
||||
var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent");
|
||||
if(attachEvent){
|
||||
// NOTE: we want to support attributes that have the form
|
||||
// "domEvent: nativeEvent; ..."
|
||||
var event, events = attachEvent.split(/\s*,\s*/);
|
||||
var trim = dojo.trim;
|
||||
while(event=events.shift()){
|
||||
if(event){
|
||||
var thisFunc = null;
|
||||
if(event.indexOf(":") != -1){
|
||||
// oh, if only JS had tuple assignment
|
||||
var funcNameArr = event.split(":");
|
||||
event = trim(funcNameArr[0]);
|
||||
thisFunc = trim(funcNameArr[1]);
|
||||
}else{
|
||||
event = trim(event);
|
||||
}
|
||||
if(!thisFunc){
|
||||
thisFunc = event;
|
||||
}
|
||||
this.connect(baseNode, event, thisFunc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// waiRole, waiState
|
||||
var role = getAttrFunc(baseNode, "waiRole");
|
||||
if(role){
|
||||
dijit.setWaiRole(baseNode, role);
|
||||
}
|
||||
var values = getAttrFunc(baseNode, "waiState");
|
||||
if(values){
|
||||
dojo.forEach(values.split(/\s*,\s*/), function(stateValue){
|
||||
if(stateValue.indexOf('-') != -1){
|
||||
var pair = stateValue.split('-');
|
||||
dijit.setWaiState(baseNode, pair[0], pair[1]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// key is either templatePath or templateString; object is either string or DOM tree
|
||||
dijit._Templated._templateCache = {};
|
||||
|
||||
dijit._Templated.getCachedTemplate = function(templatePath, templateString, alwaysUseString){
|
||||
// summary:
|
||||
// static method to get a template based on the templatePath or
|
||||
// templateString key
|
||||
// templatePath: String
|
||||
// the URL to get the template from. dojo.uri.Uri is often passed as well.
|
||||
// templateString: String?
|
||||
// a string to use in lieu of fetching the template from a URL
|
||||
// Returns:
|
||||
// Either string (if there are ${} variables that need to be replaced) or just
|
||||
// a DOM tree (if the node can be cloned directly)
|
||||
|
||||
// is it already cached?
|
||||
var tmplts = dijit._Templated._templateCache;
|
||||
var key = templateString || templatePath;
|
||||
var cached = tmplts[key];
|
||||
if(cached){
|
||||
return cached;
|
||||
}
|
||||
|
||||
// If necessary, load template string from template path
|
||||
if(!templateString){
|
||||
templateString = dijit._Templated._sanitizeTemplateString(dojo._getText(templatePath));
|
||||
}
|
||||
|
||||
templateString = dojo.string.trim(templateString);
|
||||
|
||||
if(templateString.match(/\$\{([^\}]+)\}/g) || alwaysUseString){
|
||||
// there are variables in the template so all we can do is cache the string
|
||||
return (tmplts[key] = templateString); //String
|
||||
}else{
|
||||
// there are no variables in the template so we can cache the DOM tree
|
||||
return (tmplts[key] = dijit._Templated._createNodesFromText(templateString)[0]); //Node
|
||||
}
|
||||
};
|
||||
|
||||
dijit._Templated._sanitizeTemplateString = function(/*String*/tString){
|
||||
// summary:
|
||||
// Strips <?xml ...?> declarations so that external SVG and XML
|
||||
// documents can be added to a document without worry. Also, if the string
|
||||
// is an HTML document, only the part inside the body tag is returned.
|
||||
if(tString){
|
||||
tString = tString.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
|
||||
var matches = tString.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
|
||||
if(matches){
|
||||
tString = matches[1];
|
||||
}
|
||||
}else{
|
||||
tString = "";
|
||||
}
|
||||
return tString; //String
|
||||
};
|
||||
|
||||
|
||||
if(dojo.isIE){
|
||||
dojo.addOnUnload(function(){
|
||||
var cache = dijit._Templated._templateCache;
|
||||
for(var key in cache){
|
||||
var value = cache[key];
|
||||
if(!isNaN(value.nodeType)){ // isNode equivalent
|
||||
dojo._destroyElement(value);
|
||||
}
|
||||
cache[key] = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
(function(){
|
||||
var tagMap = {
|
||||
cell: {re: /^<t[dh][\s\r\n>]/i, pre: "<table><tbody><tr>", post: "</tr></tbody></table>"},
|
||||
row: {re: /^<tr[\s\r\n>]/i, pre: "<table><tbody>", post: "</tbody></table>"},
|
||||
section: {re: /^<(thead|tbody|tfoot)[\s\r\n>]/i, pre: "<table>", post: "</table>"}
|
||||
};
|
||||
|
||||
// dummy container node used temporarily to hold nodes being created
|
||||
var tn;
|
||||
|
||||
dijit._Templated._createNodesFromText = function(/*String*/text){
|
||||
// summary:
|
||||
// Attempts to create a set of nodes based on the structure of the passed text.
|
||||
|
||||
if(!tn){
|
||||
tn = dojo.doc.createElement("div");
|
||||
tn.style.display="none";
|
||||
dojo.body().appendChild(tn);
|
||||
}
|
||||
var tableType = "none";
|
||||
var rtext = text.replace(/^\s+/, "");
|
||||
for(var type in tagMap){
|
||||
var map = tagMap[type];
|
||||
if(map.re.test(rtext)){
|
||||
tableType = type;
|
||||
text = map.pre + text + map.post;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tn.innerHTML = text;
|
||||
if(tn.normalize){
|
||||
tn.normalize();
|
||||
}
|
||||
|
||||
var tag = { cell: "tr", row: "tbody", section: "table" }[tableType];
|
||||
var _parent = (typeof tag != "undefined") ?
|
||||
tn.getElementsByTagName(tag)[0] :
|
||||
tn;
|
||||
|
||||
var nodes = [];
|
||||
while(_parent.firstChild){
|
||||
nodes.push(_parent.removeChild(_parent.firstChild));
|
||||
}
|
||||
tn.innerHTML="";
|
||||
return nodes; // Array
|
||||
}
|
||||
})();
|
||||
|
||||
// These arguments can be specified for widgets which are used in templates.
|
||||
// Since any widget can be specified as sub widgets in template, mix it
|
||||
// into the base widget class. (This is a hack, but it's effective.)
|
||||
dojo.extend(dijit._Widget,{
|
||||
dojoAttachEvent: "",
|
||||
dojoAttachPoint: "",
|
||||
waiRole: "",
|
||||
waiState:""
|
||||
})
|
||||
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._TimePicker"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._TimePicker"] = true;
|
||||
dojo.provide("dijit._TimePicker");
|
||||
|
||||
dojo.require("dijit.form._FormWidget");
|
||||
dojo.require("dojo.date.locale");
|
||||
|
||||
dojo.declare("dijit._TimePicker",
|
||||
[dijit._Widget, dijit._Templated],
|
||||
{
|
||||
// summary:
|
||||
// A graphical time picker that TimeTextBox pops up
|
||||
// It is functionally modeled after the Java applet at http://java.arcadevillage.com/applets/timepica.htm
|
||||
// See ticket #599
|
||||
|
||||
templateString:"<div id=\"widget_${id}\" class=\"dijitMenu\"\n ><div dojoAttachPoint=\"upArrow\" class=\"dijitButtonNode\"><span class=\"dijitTimePickerA11yText\">▲</span></div\n ><div dojoAttachPoint=\"timeMenu,focusNode\" dojoAttachEvent=\"onclick:_onOptionSelected,onmouseover,onmouseout\"></div\n ><div dojoAttachPoint=\"downArrow\" class=\"dijitButtonNode\"><span class=\"dijitTimePickerA11yText\">▼</span></div\n></div>\n",
|
||||
baseClass: "dijitTimePicker",
|
||||
|
||||
// clickableIncrement: String
|
||||
// ISO-8601 string representing the amount by which
|
||||
// every clickable element in the time picker increases
|
||||
// Set in non-Zulu time, without a time zone
|
||||
// Example: "T00:15:00" creates 15 minute increments
|
||||
// Must divide visibleIncrement evenly
|
||||
clickableIncrement: "T00:15:00",
|
||||
|
||||
// visibleIncrement: String
|
||||
// ISO-8601 string representing the amount by which
|
||||
// every element with a visible time in the time picker increases
|
||||
// Set in non Zulu time, without a time zone
|
||||
// Example: "T01:00:00" creates text in every 1 hour increment
|
||||
visibleIncrement: "T01:00:00",
|
||||
|
||||
// visibleRange: String
|
||||
// ISO-8601 string representing the range of this TimePicker
|
||||
// The TimePicker will only display times in this range
|
||||
// Example: "T05:00:00" displays 5 hours of options
|
||||
visibleRange: "T05:00:00",
|
||||
|
||||
// value: String
|
||||
// Date to display.
|
||||
// Defaults to current time and date.
|
||||
// Can be a Date object or an ISO-8601 string
|
||||
// If you specify the GMT time zone ("-01:00"),
|
||||
// the time will be converted to the local time in the local time zone.
|
||||
// Otherwise, the time is considered to be in the local time zone.
|
||||
// If you specify the date and isDate is true, the date is used.
|
||||
// Example: if your local time zone is GMT -05:00,
|
||||
// "T10:00:00" becomes "T10:00:00-05:00" (considered to be local time),
|
||||
// "T10:00:00-01:00" becomes "T06:00:00-05:00" (4 hour difference),
|
||||
// "T10:00:00Z" becomes "T05:00:00-05:00" (5 hour difference between Zulu and local time)
|
||||
// "yyyy-mm-ddThh:mm:ss" is the format to set the date and time
|
||||
// Example: "2007-06-01T09:00:00"
|
||||
value: new Date(),
|
||||
|
||||
_visibleIncrement:2,
|
||||
_clickableIncrement:1,
|
||||
_totalIncrements:10,
|
||||
constraints:{},
|
||||
|
||||
serialize: dojo.date.stamp.toISOString,
|
||||
|
||||
setValue:function(/*Date*/ date, /*Boolean*/ priority){
|
||||
// summary:
|
||||
// Set the value of the TimePicker
|
||||
// Redraws the TimePicker around the new date
|
||||
|
||||
//dijit._TimePicker.superclass.setValue.apply(this, arguments);
|
||||
this.value=date;
|
||||
this._showText();
|
||||
},
|
||||
|
||||
isDisabledDate: function(/*Date*/dateObject, /*String?*/locale){
|
||||
// summary:
|
||||
// May be overridden to disable certain dates in the TimePicker e.g. isDisabledDate=dojo.date.locale.isWeekend
|
||||
return false; // Boolean
|
||||
},
|
||||
|
||||
_showText:function(){
|
||||
this.timeMenu.innerHTML="";
|
||||
var fromIso = dojo.date.stamp.fromISOString;
|
||||
this._clickableIncrementDate=fromIso(this.clickableIncrement);
|
||||
this._visibleIncrementDate=fromIso(this.visibleIncrement);
|
||||
this._visibleRangeDate=fromIso(this.visibleRange);
|
||||
// get the value of the increments and the range in seconds (since 00:00:00) to find out how many divs to create
|
||||
var sinceMidnight = function(/*Date*/ date){
|
||||
return date.getHours()*60*60+date.getMinutes()*60+date.getSeconds();
|
||||
};
|
||||
|
||||
var clickableIncrementSeconds = sinceMidnight(this._clickableIncrementDate);
|
||||
var visibleIncrementSeconds = sinceMidnight(this._visibleIncrementDate);
|
||||
var visibleRangeSeconds = sinceMidnight(this._visibleRangeDate);
|
||||
|
||||
// round reference date to previous visible increment
|
||||
var time = this.value.getTime();
|
||||
this._refDate = new Date(time - time % (visibleIncrementSeconds*1000));
|
||||
|
||||
// assume clickable increment is the smallest unit
|
||||
this._clickableIncrement=1;
|
||||
// divide the visible range by the clickable increment to get the number of divs to create
|
||||
// example: 10:00:00/00:15:00 -> display 40 divs
|
||||
this._totalIncrements=visibleRangeSeconds/clickableIncrementSeconds;
|
||||
// divide the visible increments by the clickable increments to get how often to display the time inline
|
||||
// example: 01:00:00/00:15:00 -> display the time every 4 divs
|
||||
this._visibleIncrement=visibleIncrementSeconds/clickableIncrementSeconds;
|
||||
for(var i=-this._totalIncrements/2; i<=this._totalIncrements/2; i+=this._clickableIncrement){
|
||||
var div=this._createOption(i);
|
||||
this.timeMenu.appendChild(div);
|
||||
}
|
||||
|
||||
// TODO:
|
||||
// I commented this out because it
|
||||
// causes problems for a TimeTextBox in a Dialog, or as the editor of an InlineEditBox,
|
||||
// because the timeMenu node isn't visible yet. -- Bill (Bug #????)
|
||||
// dijit.focus(this.timeMenu);
|
||||
},
|
||||
|
||||
postCreate:function(){
|
||||
// instantiate constraints
|
||||
if(this.constraints===dijit._TimePicker.prototype.constraints){
|
||||
this.constraints={};
|
||||
}
|
||||
// dojo.date.locale needs the lang in the constraints as locale
|
||||
if(!this.constraints.locale){
|
||||
this.constraints.locale=this.lang;
|
||||
}
|
||||
|
||||
// assign typematic mouse listeners to the arrow buttons
|
||||
this.connect(this.timeMenu, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
|
||||
dijit.typematic.addMouseListener(this.upArrow,this,this._onArrowUp, 0.8, 500);
|
||||
dijit.typematic.addMouseListener(this.downArrow,this,this._onArrowDown, 0.8, 500);
|
||||
//dijit.typematic.addListener(this.upArrow,this.timeMenu, {keyCode:dojo.keys.UP_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_onArrowUp", 0.8, 500);
|
||||
//dijit.typematic.addListener(this.downArrow, this.timeMenu, {keyCode:dojo.keys.DOWN_ARROW,ctrlKey:false,altKey:false,shiftKey:false}, this, "_onArrowDown", 0.8,500);
|
||||
|
||||
this.inherited("postCreate", arguments);
|
||||
this.setValue(this.value);
|
||||
},
|
||||
|
||||
_createOption:function(/*Number*/ index){
|
||||
// summary: creates a clickable time option
|
||||
var div=document.createElement("div");
|
||||
var date = (div.date = new Date(this._refDate));
|
||||
div.index=index;
|
||||
var incrementDate = this._clickableIncrementDate;
|
||||
date.setHours(date.getHours()+incrementDate.getHours()*index,
|
||||
date.getMinutes()+incrementDate.getMinutes()*index,
|
||||
date.getSeconds()+incrementDate.getSeconds()*index);
|
||||
|
||||
var innerDiv = document.createElement('div');
|
||||
dojo.addClass(div,this.baseClass+"Item");
|
||||
dojo.addClass(innerDiv,this.baseClass+"ItemInner");
|
||||
innerDiv.innerHTML=dojo.date.locale.format(date, this.constraints);
|
||||
div.appendChild(innerDiv);
|
||||
|
||||
if(index%this._visibleIncrement<1 && index%this._visibleIncrement>-1){
|
||||
dojo.addClass(div, this.baseClass+"Marker");
|
||||
}else if(index%this._clickableIncrement==0){
|
||||
dojo.addClass(div, this.baseClass+"Tick");
|
||||
}
|
||||
|
||||
if(this.isDisabledDate(date)){
|
||||
// set disabled
|
||||
dojo.addClass(div, this.baseClass+"ItemDisabled");
|
||||
}
|
||||
if(dojo.date.compare(this.value, date, this.constraints.selector)==0){
|
||||
div.selected=true;
|
||||
dojo.addClass(div, this.baseClass+"ItemSelected");
|
||||
}
|
||||
return div;
|
||||
},
|
||||
|
||||
_onOptionSelected:function(/*Object*/ tgt){
|
||||
var tdate = tgt.target.date || tgt.target.parentNode.date;
|
||||
if(!tdate||this.isDisabledDate(tdate)){return;}
|
||||
this.setValue(tdate);
|
||||
this.onValueSelected(tdate);
|
||||
},
|
||||
|
||||
onValueSelected:function(value){
|
||||
},
|
||||
|
||||
onmouseover:function(/*Event*/ e){
|
||||
var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;
|
||||
this._highlighted_option=tgr;
|
||||
dojo.addClass(tgr, this.baseClass+"ItemHover");
|
||||
},
|
||||
|
||||
onmouseout:function(/*Event*/ e){
|
||||
var tgr = (e.target.parentNode === this.timeMenu) ? e.target : e.target.parentNode;
|
||||
if(this._highlighted_option===tgr){
|
||||
dojo.removeClass(tgr, this.baseClass+"ItemHover");
|
||||
}
|
||||
},
|
||||
|
||||
_mouseWheeled:function(/*Event*/e){
|
||||
// summary: handle the mouse wheel listener
|
||||
dojo.stopEvent(e);
|
||||
// we're not _measuring_ the scroll amount, just direction
|
||||
var scrollAmount = (dojo.isIE ? e.wheelDelta : -e.detail);
|
||||
this[(scrollAmount>0 ? "_onArrowUp" : "_onArrowDown")](); // yes, we're making a new dom node every time you mousewheel, or click
|
||||
},
|
||||
|
||||
_onArrowUp:function(){
|
||||
// summary: remove the bottom time and add one to the top
|
||||
var index=this.timeMenu.childNodes[0].index-1;
|
||||
var div=this._createOption(index);
|
||||
this.timeMenu.removeChild(this.timeMenu.childNodes[this.timeMenu.childNodes.length-1]);
|
||||
this.timeMenu.insertBefore(div, this.timeMenu.childNodes[0]);
|
||||
},
|
||||
|
||||
_onArrowDown:function(){
|
||||
// summary: remove the top time and add one to the bottom
|
||||
var index=this.timeMenu.childNodes[this.timeMenu.childNodes.length-1].index+1;
|
||||
var div=this._createOption(index);
|
||||
this.timeMenu.removeChild(this.timeMenu.childNodes[0]);
|
||||
this.timeMenu.appendChild(div);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,349 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._Widget"] = true;
|
||||
dojo.provide("dijit._Widget");
|
||||
|
||||
dojo.require("dijit._base");
|
||||
|
||||
dojo.declare("dijit._Widget", null, {
|
||||
// summary:
|
||||
// The foundation of dijit widgets.
|
||||
//
|
||||
// id: String
|
||||
// a unique, opaque ID string that can be assigned by users or by the
|
||||
// system. If the developer passes an ID which is known not to be
|
||||
// unique, the specified ID is ignored and the system-generated ID is
|
||||
// used instead.
|
||||
id: "",
|
||||
|
||||
// lang: String
|
||||
// Language to display this widget in (like en-us).
|
||||
// Defaults to brower's specified preferred language (typically the language of the OS)
|
||||
lang: "",
|
||||
|
||||
// dir: String
|
||||
// Bi-directional support, as defined by the HTML DIR attribute. Either left-to-right "ltr" or right-to-left "rtl".
|
||||
dir: "",
|
||||
|
||||
// class: String
|
||||
// HTML class attribute
|
||||
"class": "",
|
||||
|
||||
// style: String
|
||||
// HTML style attribute
|
||||
style: "",
|
||||
|
||||
// title: String
|
||||
// HTML title attribute
|
||||
title: "",
|
||||
|
||||
// srcNodeRef: DomNode
|
||||
// pointer to original dom node
|
||||
srcNodeRef: null,
|
||||
|
||||
// domNode: DomNode
|
||||
// this is our visible representation of the widget! Other DOM
|
||||
// Nodes may by assigned to other properties, usually through the
|
||||
// template system's dojoAttachPonit syntax, but the domNode
|
||||
// property is the canonical "top level" node in widget UI.
|
||||
domNode: null,
|
||||
|
||||
// attributeMap: Object
|
||||
// A map of attributes and attachpoints -- typically standard HTML attributes -- to set
|
||||
// on the widget's dom, at the "domNode" attach point, by default.
|
||||
// Other node references can be specified as properties of 'this'
|
||||
attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""}, // TODO: add on* handlers?
|
||||
|
||||
//////////// INITIALIZATION METHODS ///////////////////////////////////////
|
||||
|
||||
postscript: function(params, srcNodeRef){
|
||||
this.create(params, srcNodeRef);
|
||||
},
|
||||
|
||||
create: function(params, srcNodeRef){
|
||||
// summary:
|
||||
// To understand the process by which widgets are instantiated, it
|
||||
// is critical to understand what other methods create calls and
|
||||
// which of them you'll want to override. Of course, adventurous
|
||||
// developers could override create entirely, but this should
|
||||
// only be done as a last resort.
|
||||
//
|
||||
// Below is a list of the methods that are called, in the order
|
||||
// they are fired, along with notes about what they do and if/when
|
||||
// you should over-ride them in your widget:
|
||||
//
|
||||
// postMixInProperties:
|
||||
// a stub function that you can over-ride to modify
|
||||
// variables that may have been naively assigned by
|
||||
// mixInProperties
|
||||
// # widget is added to manager object here
|
||||
// buildRendering
|
||||
// Subclasses use this method to handle all UI initialization
|
||||
// Sets this.domNode. Templated widgets do this automatically
|
||||
// and otherwise it just uses the source dom node.
|
||||
// postCreate
|
||||
// a stub function that you can over-ride to modify take
|
||||
// actions once the widget has been placed in the UI
|
||||
|
||||
// store pointer to original dom tree
|
||||
this.srcNodeRef = dojo.byId(srcNodeRef);
|
||||
|
||||
// For garbage collection. An array of handles returned by Widget.connect()
|
||||
// Each handle returned from Widget.connect() is an array of handles from dojo.connect()
|
||||
this._connects=[];
|
||||
|
||||
// _attaches: String[]
|
||||
// names of all our dojoAttachPoint variables
|
||||
this._attaches=[];
|
||||
|
||||
//mixin our passed parameters
|
||||
if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
|
||||
if(params){
|
||||
dojo.mixin(this,params);
|
||||
}
|
||||
this.postMixInProperties();
|
||||
|
||||
// generate an id for the widget if one wasn't specified
|
||||
// (be sure to do this before buildRendering() because that function might
|
||||
// expect the id to be there.
|
||||
if(!this.id){
|
||||
this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
|
||||
}
|
||||
dijit.registry.add(this);
|
||||
|
||||
this.buildRendering();
|
||||
|
||||
// Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
|
||||
// The placement of these attributes is according to the property mapping in attributeMap.
|
||||
// Note special handling for 'style' and 'class' attributes which are lists and can
|
||||
// have elements from both old and new structures, and some attributes like "type"
|
||||
// cannot be processed this way as they are not mutable.
|
||||
if(this.domNode){
|
||||
for(var attr in this.attributeMap){
|
||||
var mapNode = this[this.attributeMap[attr] || "domNode"];
|
||||
var value = this[attr];
|
||||
if(typeof value != "object" && (value !== "" || (params && params[attr]))){
|
||||
switch(attr){
|
||||
case "class":
|
||||
dojo.addClass(mapNode, value);
|
||||
break;
|
||||
case "style":
|
||||
if(mapNode.style.cssText){
|
||||
mapNode.style.cssText += "; " + value;// FIXME: Opera
|
||||
}else{
|
||||
mapNode.style.cssText = value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mapNode.setAttribute(attr, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(this.domNode){
|
||||
this.domNode.setAttribute("widgetId", this.id);
|
||||
}
|
||||
this.postCreate();
|
||||
|
||||
// If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
|
||||
if(this.srcNodeRef && !this.srcNodeRef.parentNode){
|
||||
delete this.srcNodeRef;
|
||||
}
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
// summary
|
||||
// Called after the parameters to the widget have been read-in,
|
||||
// but before the widget template is instantiated.
|
||||
// Especially useful to set properties that are referenced in the widget template.
|
||||
},
|
||||
|
||||
buildRendering: function(){
|
||||
// summary:
|
||||
// Construct the UI for this widget, setting this.domNode.
|
||||
// Most widgets will mixin TemplatedWidget, which overrides this method.
|
||||
this.domNode = this.srcNodeRef || dojo.doc.createElement('div');
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
// summary:
|
||||
// Called after a widget's dom has been setup
|
||||
},
|
||||
|
||||
startup: function(){
|
||||
// summary:
|
||||
// Called after a widget's children, and other widgets on the page, have been created.
|
||||
// Provides an opportunity to manipulate any children before they are displayed
|
||||
// This is useful for composite widgets that need to control or layout sub-widgets
|
||||
// Many layout widgets can use this as a wiring phase
|
||||
},
|
||||
|
||||
//////////// DESTROY FUNCTIONS ////////////////////////////////
|
||||
|
||||
destroyRecursive: function(/*Boolean*/ finalize){
|
||||
// summary:
|
||||
// Destroy this widget and it's descendants. This is the generic
|
||||
// "destructor" function that all widget users should call to
|
||||
// cleanly discard with a widget. Once a widget is destroyed, it's
|
||||
// removed from the manager object.
|
||||
// finalize: Boolean
|
||||
// is this function being called part of global environment
|
||||
// tear-down?
|
||||
|
||||
this.destroyDescendants();
|
||||
this.destroy();
|
||||
},
|
||||
|
||||
destroy: function(/*Boolean*/ finalize){
|
||||
// summary:
|
||||
// Destroy this widget, but not its descendants
|
||||
// finalize: Boolean
|
||||
// is this function being called part of global environment
|
||||
// tear-down?
|
||||
this.uninitialize();
|
||||
dojo.forEach(this._connects, function(array){
|
||||
dojo.forEach(array, dojo.disconnect);
|
||||
});
|
||||
this.destroyRendering(finalize);
|
||||
dijit.registry.remove(this.id);
|
||||
},
|
||||
|
||||
destroyRendering: function(/*Boolean*/ finalize){
|
||||
// summary:
|
||||
// Destroys the DOM nodes associated with this widget
|
||||
// finalize: Boolean
|
||||
// is this function being called part of global environment
|
||||
// tear-down?
|
||||
|
||||
if(this.bgIframe){
|
||||
this.bgIframe.destroy();
|
||||
delete this.bgIframe;
|
||||
}
|
||||
|
||||
if(this.domNode){
|
||||
dojo._destroyElement(this.domNode);
|
||||
delete this.domNode;
|
||||
}
|
||||
|
||||
if(this.srcNodeRef){
|
||||
dojo._destroyElement(this.srcNodeRef);
|
||||
delete this.srcNodeRef;
|
||||
}
|
||||
},
|
||||
|
||||
destroyDescendants: function(){
|
||||
// summary:
|
||||
// Recursively destroy the children of this widget and their
|
||||
// descendants.
|
||||
|
||||
// TODO: should I destroy in the reverse order, to go bottom up?
|
||||
dojo.forEach(this.getDescendants(), function(widget){ widget.destroy(); });
|
||||
},
|
||||
|
||||
uninitialize: function(){
|
||||
// summary:
|
||||
// stub function. Over-ride to implement custom widget tear-down
|
||||
// behavior.
|
||||
return false;
|
||||
},
|
||||
|
||||
////////////////// MISCELLANEOUS METHODS ///////////////////
|
||||
|
||||
toString: function(){
|
||||
// summary:
|
||||
// returns a string that represents the widget. When a widget is
|
||||
// cast to a string, this method will be used to generate the
|
||||
// output. Currently, it does not implement any sort of reversable
|
||||
// serialization.
|
||||
return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
|
||||
},
|
||||
|
||||
getDescendants: function(){
|
||||
// summary:
|
||||
// return all the descendant widgets
|
||||
var list = dojo.query('[widgetId]', this.domNode);
|
||||
return list.map(dijit.byNode); // Array
|
||||
},
|
||||
|
||||
nodesWithKeyClick : ["input", "button"],
|
||||
|
||||
connect: function(
|
||||
/*Object|null*/ obj,
|
||||
/*String*/ event,
|
||||
/*String|Function*/ method){
|
||||
|
||||
// summary:
|
||||
// Connects specified obj/event to specified method of this object
|
||||
// and registers for disconnect() on widget destroy.
|
||||
// Special event: "ondijitclick" triggers on a click or enter-down or space-up
|
||||
// Similar to dojo.connect() but takes three arguments rather than four.
|
||||
var handles =[];
|
||||
if(event == "ondijitclick"){
|
||||
var w = this;
|
||||
// add key based click activation for unsupported nodes.
|
||||
if(!this.nodesWithKeyClick[obj.nodeName]){
|
||||
handles.push(dojo.connect(obj, "onkeydown", this,
|
||||
function(e){
|
||||
if(e.keyCode == dojo.keys.ENTER){
|
||||
return (dojo.isString(method))?
|
||||
w[method](e) : method.call(w, e);
|
||||
}else if(e.keyCode == dojo.keys.SPACE){
|
||||
// stop space down as it causes IE to scroll
|
||||
// the browser window
|
||||
dojo.stopEvent(e);
|
||||
}
|
||||
}));
|
||||
handles.push(dojo.connect(obj, "onkeyup", this,
|
||||
function(e){
|
||||
if(e.keyCode == dojo.keys.SPACE){
|
||||
return dojo.isString(method) ?
|
||||
w[method](e) : method.call(w, e);
|
||||
}
|
||||
}));
|
||||
}
|
||||
event = "onclick";
|
||||
}
|
||||
handles.push(dojo.connect(obj, event, this, method));
|
||||
|
||||
// return handles for FormElement and ComboBox
|
||||
this._connects.push(handles);
|
||||
return handles;
|
||||
},
|
||||
|
||||
disconnect: function(/*Object*/ handles){
|
||||
// summary:
|
||||
// Disconnects handle created by this.connect.
|
||||
// Also removes handle from this widget's list of connects
|
||||
for(var i=0; i<this._connects.length; i++){
|
||||
if(this._connects[i]==handles){
|
||||
dojo.forEach(handles, dojo.disconnect);
|
||||
this._connects.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
isLeftToRight: function(){
|
||||
// summary:
|
||||
// Checks the DOM to for the text direction for bi-directional support
|
||||
// description:
|
||||
// This method cannot be used during widget construction because the widget
|
||||
// must first be connected to the DOM tree. Parent nodes are searched for the
|
||||
// 'dir' attribute until one is found, otherwise left to right mode is assumed.
|
||||
// See HTML spec, DIR attribute for more information.
|
||||
|
||||
if(typeof this._ltr == "undefined"){
|
||||
this._ltr = dojo.getComputedStyle(this.domNode).direction != "rtl";
|
||||
}
|
||||
return this._ltr; //Boolean
|
||||
},
|
||||
|
||||
isFocusable: function(){
|
||||
// summary:
|
||||
// Return true if this widget can currently be focused
|
||||
// and false if not
|
||||
return this.focus && (dojo.style(this.domNode, "display") != "none");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base"] = true;
|
||||
dojo.provide("dijit._base");
|
||||
|
||||
dojo.require("dijit._base.focus");
|
||||
dojo.require("dijit._base.manager");
|
||||
dojo.require("dijit._base.place");
|
||||
dojo.require("dijit._base.popup");
|
||||
dojo.require("dijit._base.scroll");
|
||||
dojo.require("dijit._base.sniff");
|
||||
dojo.require("dijit._base.bidi");
|
||||
dojo.require("dijit._base.typematic");
|
||||
dojo.require("dijit._base.wai");
|
||||
dojo.require("dijit._base.window");
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.bidi"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.bidi"] = true;
|
||||
dojo.provide("dijit._base.bidi");
|
||||
|
||||
// summary: applies a class to the top of the document for right-to-left stylesheet rules
|
||||
|
||||
dojo.addOnLoad(function(){
|
||||
if(!dojo._isBodyLtr()){
|
||||
dojo.addClass(dojo.body(), "dijitRtl");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,330 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.focus"] = true;
|
||||
dojo.provide("dijit._base.focus");
|
||||
|
||||
// summary:
|
||||
// These functions are used to query or set the focus and selection.
|
||||
//
|
||||
// Also, they trace when widgets become actived/deactivated,
|
||||
// so that the widget can fire _onFocus/_onBlur events.
|
||||
// "Active" here means something similar to "focused", but
|
||||
// "focus" isn't quite the right word because we keep track of
|
||||
// a whole stack of "active" widgets. Example: Combobutton --> Menu -->
|
||||
// MenuItem. The onBlur event for Combobutton doesn't fire due to focusing
|
||||
// on the Menu or a MenuItem, since they are considered part of the
|
||||
// Combobutton widget. It only happens when focus is shifted
|
||||
// somewhere completely different.
|
||||
|
||||
dojo.mixin(dijit,
|
||||
{
|
||||
// _curFocus: DomNode
|
||||
// Currently focused item on screen
|
||||
_curFocus: null,
|
||||
|
||||
// _prevFocus: DomNode
|
||||
// Previously focused item on screen
|
||||
_prevFocus: null,
|
||||
|
||||
isCollapsed: function(){
|
||||
// summary: tests whether the current selection is empty
|
||||
var _window = dojo.global;
|
||||
var _document = dojo.doc;
|
||||
if(_document.selection){ // IE
|
||||
return !_document.selection.createRange().text; // Boolean
|
||||
}else if(_window.getSelection){
|
||||
var selection = _window.getSelection();
|
||||
if(dojo.isString(selection)){ // Safari
|
||||
return !selection; // Boolean
|
||||
}else{ // Mozilla/W3
|
||||
return selection.isCollapsed || !selection.toString(); // Boolean
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getBookmark: function(){
|
||||
// summary: Retrieves a bookmark that can be used with moveToBookmark to return to the same range
|
||||
var bookmark, selection = dojo.doc.selection;
|
||||
if(selection){ // IE
|
||||
var range = selection.createRange();
|
||||
if(selection.type.toUpperCase()=='CONTROL'){
|
||||
bookmark = range.length ? dojo._toArray(range) : null;
|
||||
}else{
|
||||
bookmark = range.getBookmark();
|
||||
}
|
||||
}else{
|
||||
if(dojo.global.getSelection){
|
||||
selection = dojo.global.getSelection();
|
||||
if(selection){
|
||||
var range = selection.getRangeAt(0);
|
||||
bookmark = range.cloneRange();
|
||||
}
|
||||
}else{
|
||||
console.debug("No idea how to store the current selection for this browser!");
|
||||
}
|
||||
}
|
||||
return bookmark; // Array
|
||||
},
|
||||
|
||||
moveToBookmark: function(/*Object*/bookmark){
|
||||
// summary: Moves current selection to a bookmark
|
||||
// bookmark: this should be a returned object from dojo.html.selection.getBookmark()
|
||||
var _document = dojo.doc;
|
||||
if(_document.selection){ // IE
|
||||
var range;
|
||||
if(dojo.isArray(bookmark)){
|
||||
range = _document.body.createControlRange();
|
||||
dojo.forEach(bookmark, range.addElement);
|
||||
}else{
|
||||
range = _document.selection.createRange();
|
||||
range.moveToBookmark(bookmark);
|
||||
}
|
||||
range.select();
|
||||
}else{ //Moz/W3C
|
||||
var selection = dojo.global.getSelection && dojo.global.getSelection();
|
||||
if(selection && selection.removeAllRanges){
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(bookmark);
|
||||
}else{
|
||||
console.debug("No idea how to restore selection for this browser!");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getFocus: function(/*Widget*/menu, /*Window*/ openedForWindow){
|
||||
// summary:
|
||||
// Returns the current focus and selection.
|
||||
// Called when a popup appears (either a top level menu or a dialog),
|
||||
// or when a toolbar/menubar receives focus
|
||||
//
|
||||
// menu:
|
||||
// the menu that's being opened
|
||||
//
|
||||
// openedForWindow:
|
||||
// iframe in which menu was opened
|
||||
//
|
||||
// returns:
|
||||
// a handle to restore focus/selection
|
||||
|
||||
return {
|
||||
// Node to return focus to
|
||||
node: menu && dojo.isDescendant(dijit._curFocus, menu.domNode) ? dijit._prevFocus : dijit._curFocus,
|
||||
|
||||
// Previously selected text
|
||||
bookmark:
|
||||
!dojo.withGlobal(openedForWindow||dojo.global, dijit.isCollapsed) ?
|
||||
dojo.withGlobal(openedForWindow||dojo.global, dijit.getBookmark) :
|
||||
null,
|
||||
|
||||
openedForWindow: openedForWindow
|
||||
}; // Object
|
||||
},
|
||||
|
||||
focus: function(/*Object || DomNode */ handle){
|
||||
// summary:
|
||||
// Sets the focused node and the selection according to argument.
|
||||
// To set focus to an iframe's content, pass in the iframe itself.
|
||||
// handle:
|
||||
// object returned by get(), or a DomNode
|
||||
|
||||
if(!handle){ return; }
|
||||
|
||||
var node = "node" in handle ? handle.node : handle, // because handle is either DomNode or a composite object
|
||||
bookmark = handle.bookmark,
|
||||
openedForWindow = handle.openedForWindow;
|
||||
|
||||
// Set the focus
|
||||
// Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
|
||||
// but we need to set focus to iframe.contentWindow
|
||||
if(node){
|
||||
var focusNode = (node.tagName.toLowerCase()=="iframe") ? node.contentWindow : node;
|
||||
if(focusNode && focusNode.focus){
|
||||
try{
|
||||
// Gecko throws sometimes if setting focus is impossible,
|
||||
// node not displayed or something like that
|
||||
focusNode.focus();
|
||||
}catch(e){/*quiet*/}
|
||||
}
|
||||
dijit._onFocusNode(node);
|
||||
}
|
||||
|
||||
// set the selection
|
||||
// do not need to restore if current selection is not empty
|
||||
// (use keyboard to select a menu item)
|
||||
if(bookmark && dojo.withGlobal(openedForWindow||dojo.global, dijit.isCollapsed)){
|
||||
if(openedForWindow){
|
||||
openedForWindow.focus();
|
||||
}
|
||||
try{
|
||||
dojo.withGlobal(openedForWindow||dojo.global, moveToBookmark, null, [bookmark]);
|
||||
}catch(e){
|
||||
/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// List of currently active widgets (focused widget and it's ancestors)
|
||||
_activeStack: [],
|
||||
|
||||
registerWin: function(/*Window?*/targetWindow){
|
||||
// summary:
|
||||
// Registers listeners on the specified window (either the main
|
||||
// window or an iframe) to detect when the user has clicked somewhere.
|
||||
// Anyone that creates an iframe should call this function.
|
||||
|
||||
if(!targetWindow){
|
||||
targetWindow = window;
|
||||
}
|
||||
|
||||
dojo.connect(targetWindow.document, "onmousedown", null, function(evt){
|
||||
dijit._justMouseDowned = true;
|
||||
setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
|
||||
dijit._onTouchNode(evt.target||evt.srcElement);
|
||||
});
|
||||
//dojo.connect(targetWindow, "onscroll", ???);
|
||||
|
||||
// Listen for blur and focus events on targetWindow's body
|
||||
var body = targetWindow.document.body || targetWindow.document.getElementsByTagName("body")[0];
|
||||
if(body){
|
||||
if(dojo.isIE){
|
||||
body.attachEvent('onactivate', function(evt){
|
||||
if(evt.srcElement.tagName.toLowerCase() != "body"){
|
||||
dijit._onFocusNode(evt.srcElement);
|
||||
}
|
||||
});
|
||||
body.attachEvent('ondeactivate', function(evt){ dijit._onBlurNode(evt.srcElement); });
|
||||
}else{
|
||||
body.addEventListener('focus', function(evt){ dijit._onFocusNode(evt.target); }, true);
|
||||
body.addEventListener('blur', function(evt){ dijit._onBlurNode(evt.target); }, true);
|
||||
}
|
||||
}
|
||||
body = null; // prevent memory leak (apparent circular reference via closure)
|
||||
},
|
||||
|
||||
_onBlurNode: function(/*DomNode*/ node){
|
||||
// summary:
|
||||
// Called when focus leaves a node.
|
||||
// Usually ignored, _unless_ it *isn't* follwed by touching another node,
|
||||
// which indicates that we tabbed off the last field on the page,
|
||||
// in which case every widget is marked inactive
|
||||
dijit._prevFocus = dijit._curFocus;
|
||||
dijit._curFocus = null;
|
||||
|
||||
var w = dijit.getEnclosingWidget(node);
|
||||
if (w && w._setStateClass){
|
||||
w._focused = false;
|
||||
w._setStateClass();
|
||||
}
|
||||
if(dijit._justMouseDowned){
|
||||
// the mouse down caused a new widget to be marked as active; this blur event
|
||||
// is coming late, so ignore it.
|
||||
return;
|
||||
}
|
||||
|
||||
// if the blur event isn't followed by a focus event then mark all widgets as inactive.
|
||||
if(dijit._clearActiveWidgetsTimer){
|
||||
clearTimeout(dijit._clearActiveWidgetsTimer);
|
||||
}
|
||||
dijit._clearActiveWidgetsTimer = setTimeout(function(){
|
||||
delete dijit._clearActiveWidgetsTimer; dijit._setStack([]); }, 100);
|
||||
},
|
||||
|
||||
_onTouchNode: function(/*DomNode*/ node){
|
||||
// summary
|
||||
// Callback when node is focused or mouse-downed
|
||||
|
||||
// ignore the recent blurNode event
|
||||
if(dijit._clearActiveWidgetsTimer){
|
||||
clearTimeout(dijit._clearActiveWidgetsTimer);
|
||||
delete dijit._clearActiveWidgetsTimer;
|
||||
}
|
||||
|
||||
// compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
|
||||
var newStack=[];
|
||||
try{
|
||||
while(node){
|
||||
if(node.dijitPopupParent){
|
||||
node=dijit.byId(node.dijitPopupParent).domNode;
|
||||
}else if(node.tagName && node.tagName.toLowerCase()=="body"){
|
||||
// is this the root of the document or just the root of an iframe?
|
||||
if(node===dojo.body()){
|
||||
// node is the root of the main document
|
||||
break;
|
||||
}
|
||||
// otherwise, find the iframe this node refers to (can't access it via parentNode,
|
||||
// need to do this trick instead) and continue tracing up the document
|
||||
node=dojo.query("iframe").filter(function(iframe){ return iframe.contentDocument.body===node; })[0];
|
||||
}else{
|
||||
var id = node.getAttribute && node.getAttribute("widgetId");
|
||||
if(id){
|
||||
newStack.unshift(id);
|
||||
}
|
||||
node=node.parentNode;
|
||||
}
|
||||
}
|
||||
}catch(e){ /* squelch */ }
|
||||
|
||||
dijit._setStack(newStack);
|
||||
},
|
||||
|
||||
_onFocusNode: function(/*DomNode*/ node){
|
||||
// summary
|
||||
// Callback when node is focused
|
||||
if(node && node.tagName && node.tagName.toLowerCase() == "body"){
|
||||
return;
|
||||
}
|
||||
dijit._onTouchNode(node);
|
||||
if(node==dijit._curFocus){ return; }
|
||||
dijit._prevFocus = dijit._curFocus;
|
||||
dijit._curFocus = node;
|
||||
dojo.publish("focusNode", [node]);
|
||||
|
||||
// handle focus/blur styling
|
||||
var w = dijit.getEnclosingWidget(node);
|
||||
if (w && w._setStateClass){
|
||||
w._focused = true;
|
||||
w._setStateClass();
|
||||
}
|
||||
},
|
||||
|
||||
_setStack: function(newStack){
|
||||
// summary
|
||||
// The stack of active widgets has changed. Send out appropriate events and record new stack
|
||||
|
||||
var oldStack = dijit._activeStack;
|
||||
dijit._activeStack = newStack;
|
||||
|
||||
// compare old stack to new stack to see how many elements they have in common
|
||||
for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){
|
||||
if(oldStack[nCommon] != newStack[nCommon]){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// for all elements that have gone out of focus, send blur event
|
||||
for(var i=oldStack.length-1; i>=nCommon; i--){
|
||||
var widget = dijit.byId(oldStack[i]);
|
||||
if(widget){
|
||||
dojo.publish("widgetBlur", [widget]);
|
||||
if(widget._onBlur){
|
||||
widget._onBlur();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// for all element that have come into focus, send focus event
|
||||
for(var i=nCommon; i<newStack.length; i++){
|
||||
var widget = dijit.byId(newStack[i]);
|
||||
if(widget){
|
||||
dojo.publish("widgetFocus", [widget]);
|
||||
if(widget._onFocus){
|
||||
widget._onFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// register top window and all the iframes it contains
|
||||
dojo.addOnLoad(dijit.registerWin);
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.manager"] = true;
|
||||
dojo.provide("dijit._base.manager");
|
||||
|
||||
dojo.declare("dijit.WidgetSet", null, {
|
||||
constructor: function(){
|
||||
// summary:
|
||||
// A set of widgets indexed by id
|
||||
this._hash={};
|
||||
},
|
||||
|
||||
add: function(/*Widget*/ widget){
|
||||
if(this._hash[widget.id]){
|
||||
throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
|
||||
}
|
||||
this._hash[widget.id]=widget;
|
||||
},
|
||||
|
||||
remove: function(/*String*/ id){
|
||||
delete this._hash[id];
|
||||
},
|
||||
|
||||
forEach: function(/*Function*/ func){
|
||||
for(var id in this._hash){
|
||||
func(this._hash[id]);
|
||||
}
|
||||
},
|
||||
|
||||
filter: function(/*Function*/ filter){
|
||||
var res = new dijit.WidgetSet();
|
||||
this.forEach(function(widget){
|
||||
if(filter(widget)){ res.add(widget); }
|
||||
});
|
||||
return res; // dijit.WidgetSet
|
||||
},
|
||||
|
||||
byId: function(/*String*/ id){
|
||||
return this._hash[id];
|
||||
},
|
||||
|
||||
byClass: function(/*String*/ cls){
|
||||
return this.filter(function(widget){ return widget.declaredClass==cls; }); // dijit.WidgetSet
|
||||
}
|
||||
});
|
||||
|
||||
// registry: list of all widgets on page
|
||||
dijit.registry = new dijit.WidgetSet();
|
||||
|
||||
dijit._widgetTypeCtr = {};
|
||||
|
||||
dijit.getUniqueId = function(/*String*/widgetType){
|
||||
// summary
|
||||
// Generates a unique id for a given widgetType
|
||||
|
||||
var id;
|
||||
do{
|
||||
id = widgetType + "_" +
|
||||
(dijit._widgetTypeCtr[widgetType] !== undefined ?
|
||||
++dijit._widgetTypeCtr[widgetType] : dijit._widgetTypeCtr[widgetType] = 0);
|
||||
}while(dijit.byId(id));
|
||||
return id; // String
|
||||
};
|
||||
|
||||
|
||||
if(dojo.isIE){
|
||||
// Only run this for IE because we think it's only necessary in that case,
|
||||
// and because it causes problems on FF. See bug #3531 for details.
|
||||
dojo.addOnUnload(function(){
|
||||
dijit.registry.forEach(function(widget){ widget.destroy(); });
|
||||
});
|
||||
}
|
||||
|
||||
dijit.byId = function(/*String|Widget*/id){
|
||||
// summary:
|
||||
// Returns a widget by its id, or if passed a widget, no-op (like dojo.byId())
|
||||
return (dojo.isString(id)) ? dijit.registry.byId(id) : id; // Widget
|
||||
};
|
||||
|
||||
dijit.byNode = function(/* DOMNode */ node){
|
||||
// summary:
|
||||
// Returns the widget as referenced by node
|
||||
return dijit.registry.byId(node.getAttribute("widgetId")); // Widget
|
||||
};
|
||||
|
||||
dijit.getEnclosingWidget = function(/* DOMNode */ node){
|
||||
// summary:
|
||||
// Returns the widget whose dom tree contains node or null if
|
||||
// the node is not contained within the dom tree of any widget
|
||||
while(node){
|
||||
if(node.getAttribute && node.getAttribute("widgetId")){
|
||||
return dijit.registry.byId(node.getAttribute("widgetId"));
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.place"] = true;
|
||||
dojo.provide("dijit._base.place");
|
||||
|
||||
// ported from dojo.html.util
|
||||
|
||||
dijit.getViewport = function(){
|
||||
// summary
|
||||
// Returns the dimensions and scroll position of the viewable area of a browser window
|
||||
|
||||
var _window = dojo.global;
|
||||
var _document = dojo.doc;
|
||||
|
||||
// get viewport size
|
||||
var w = 0, h = 0;
|
||||
if(dojo.isMozilla){
|
||||
// mozilla
|
||||
// _window.innerHeight includes the height taken by the scroll bar
|
||||
// clientHeight is ideal but has DTD issues:
|
||||
// #4539: FF reverses the roles of body.clientHeight/Width and documentElement.clientHeight/Width based on the DTD!
|
||||
// check DTD to see whether body or documentElement returns the viewport dimensions using this algorithm:
|
||||
var minw, minh, maxw, maxh;
|
||||
if(_document.body.clientWidth>_document.documentElement.clientWidth){
|
||||
minw = _document.documentElement.clientWidth;
|
||||
maxw = _document.body.clientWidth;
|
||||
}else{
|
||||
maxw = _document.documentElement.clientWidth;
|
||||
minw = _document.body.clientWidth;
|
||||
}
|
||||
if(_document.body.clientHeight>_document.documentElement.clientHeight){
|
||||
minh = _document.documentElement.clientHeight;
|
||||
maxh = _document.body.clientHeight;
|
||||
}else{
|
||||
maxh = _document.documentElement.clientHeight;
|
||||
minh = _document.body.clientHeight;
|
||||
}
|
||||
w = (maxw > _window.innerWidth) ? minw : maxw;
|
||||
h = (maxh > _window.innerHeight) ? minh : maxh;
|
||||
}else if(!dojo.isOpera && _window.innerWidth){
|
||||
//in opera9, dojo.body().clientWidth should be used, instead
|
||||
//of window.innerWidth/document.documentElement.clientWidth
|
||||
//so we have to check whether it is opera
|
||||
w = _window.innerWidth;
|
||||
h = _window.innerHeight;
|
||||
}else if(dojo.isIE && _document.documentElement && _document.documentElement.clientHeight){
|
||||
w = _document.documentElement.clientWidth;
|
||||
h = _document.documentElement.clientHeight;
|
||||
}else if(dojo.body().clientWidth){
|
||||
// IE5, Opera
|
||||
w = dojo.body().clientWidth;
|
||||
h = dojo.body().clientHeight;
|
||||
}
|
||||
|
||||
// get scroll position
|
||||
var scroll = dojo._docScroll();
|
||||
|
||||
return { w: w, h: h, l: scroll.x, t: scroll.y }; // object
|
||||
};
|
||||
|
||||
dijit.placeOnScreen = function(
|
||||
/* DomNode */ node,
|
||||
/* Object */ pos,
|
||||
/* Object */ corners,
|
||||
/* boolean? */ tryOnly){
|
||||
// summary:
|
||||
// Keeps 'node' in the visible area of the screen while trying to
|
||||
// place closest to pos.x, pos.y. The input coordinates are
|
||||
// expected to be the desired document position.
|
||||
//
|
||||
// Set which corner(s) you want to bind to, such as
|
||||
//
|
||||
// placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"])
|
||||
//
|
||||
// The desired x/y will be treated as the topleft(TL)/topright(TR) or
|
||||
// BottomLeft(BL)/BottomRight(BR) corner of the node. Each corner is tested
|
||||
// and if a perfect match is found, it will be used. Otherwise, it goes through
|
||||
// all of the specified corners, and choose the most appropriate one.
|
||||
//
|
||||
// NOTE: node is assumed to be absolutely or relatively positioned.
|
||||
|
||||
var choices = dojo.map(corners, function(corner){ return { corner: corner, pos: pos }; });
|
||||
|
||||
return dijit._place(node, choices);
|
||||
}
|
||||
|
||||
dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){
|
||||
// summary:
|
||||
// Given a list of spots to put node, put it at the first spot where it fits,
|
||||
// of if it doesn't fit anywhere then the place with the least overflow
|
||||
// choices: Array
|
||||
// Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
|
||||
// Above example says to put the top-left corner of the node at (10,20)
|
||||
// layoutNode: Function(node, orient)
|
||||
// for things like tooltip, they are displayed differently (and have different dimensions)
|
||||
// based on their orientation relative to the parent. This adjusts the popup based on orientation.
|
||||
|
||||
// get {x: 10, y: 10, w: 100, h:100} type obj representing position of
|
||||
// viewport over document
|
||||
var view = dijit.getViewport();
|
||||
|
||||
// This won't work if the node is inside a <div style="position: relative">,
|
||||
// so reattach it to document.body. (Otherwise, the positioning will be wrong
|
||||
// and also it might get cutoff)
|
||||
if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
|
||||
dojo.body().appendChild(node);
|
||||
}
|
||||
|
||||
var best=null;
|
||||
for(var i=0; i<choices.length; i++){
|
||||
var corner = choices[i].corner;
|
||||
var pos = choices[i].pos;
|
||||
|
||||
// configure node to be displayed in given position relative to button
|
||||
// (need to do this in order to get an accurate size for the node, because
|
||||
// a tooltips size changes based on position, due to triangle)
|
||||
if(layoutNode){
|
||||
layoutNode(corner);
|
||||
}
|
||||
|
||||
// get node's size
|
||||
var oldDisplay = node.style.display;
|
||||
var oldVis = node.style.visibility;
|
||||
node.style.visibility = "hidden";
|
||||
node.style.display = "";
|
||||
var mb = dojo.marginBox(node);
|
||||
node.style.display = oldDisplay;
|
||||
node.style.visibility = oldVis;
|
||||
|
||||
// coordinates and size of node with specified corner placed at pos,
|
||||
// and clipped by viewport
|
||||
var startX = (corner.charAt(1)=='L' ? pos.x : Math.max(view.l, pos.x - mb.w)),
|
||||
startY = (corner.charAt(0)=='T' ? pos.y : Math.max(view.t, pos.y - mb.h)),
|
||||
endX = (corner.charAt(1)=='L' ? Math.min(view.l+view.w, startX+mb.w) : pos.x),
|
||||
endY = (corner.charAt(0)=='T' ? Math.min(view.t+view.h, startY+mb.h) : pos.y),
|
||||
width = endX-startX,
|
||||
height = endY-startY,
|
||||
overflow = (mb.w-width) + (mb.h-height);
|
||||
|
||||
if(best==null || overflow<best.overflow){
|
||||
best = {
|
||||
corner: corner,
|
||||
aroundCorner: choices[i].aroundCorner,
|
||||
x: startX,
|
||||
y: startY,
|
||||
w: width,
|
||||
h: height,
|
||||
overflow: overflow
|
||||
};
|
||||
}
|
||||
if(overflow==0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
node.style.left = best.x + "px";
|
||||
node.style.top = best.y + "px";
|
||||
return best;
|
||||
}
|
||||
|
||||
dijit.placeOnScreenAroundElement = function(
|
||||
/* DomNode */ node,
|
||||
/* DomNode */ aroundNode,
|
||||
/* Object */ aroundCorners,
|
||||
/* Function */ layoutNode){
|
||||
|
||||
// summary
|
||||
// Like placeOnScreen, except it accepts aroundNode instead of x,y
|
||||
// and attempts to place node around it. Uses margin box dimensions.
|
||||
//
|
||||
// aroundCorners
|
||||
// specify Which corner of aroundNode should be
|
||||
// used to place the node => which corner(s) of node to use (see the
|
||||
// corners parameter in dijit.placeOnScreen)
|
||||
// e.g. {'TL': 'BL', 'BL': 'TL'}
|
||||
//
|
||||
// layoutNode: Function(node, orient)
|
||||
// for things like tooltip, they are displayed differently (and have different dimensions)
|
||||
// based on their orientation relative to the parent. This adjusts the popup based on orientation.
|
||||
|
||||
|
||||
// get coordinates of aroundNode
|
||||
aroundNode = dojo.byId(aroundNode);
|
||||
var oldDisplay = aroundNode.style.display;
|
||||
aroundNode.style.display="";
|
||||
// #3172: use the slightly tighter border box instead of marginBox
|
||||
var aroundNodeW = aroundNode.offsetWidth; //mb.w;
|
||||
var aroundNodeH = aroundNode.offsetHeight; //mb.h;
|
||||
var aroundNodePos = dojo.coords(aroundNode, true);
|
||||
aroundNode.style.display=oldDisplay;
|
||||
|
||||
// Generate list of possible positions for node
|
||||
var choices = [];
|
||||
for(var nodeCorner in aroundCorners){
|
||||
choices.push( {
|
||||
aroundCorner: nodeCorner,
|
||||
corner: aroundCorners[nodeCorner],
|
||||
pos: {
|
||||
x: aroundNodePos.x + (nodeCorner.charAt(1)=='L' ? 0 : aroundNodeW),
|
||||
y: aroundNodePos.y + (nodeCorner.charAt(0)=='T' ? 0 : aroundNodeH)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return dijit._place(node, choices, layoutNode);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,240 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.popup"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.popup"] = true;
|
||||
dojo.provide("dijit._base.popup");
|
||||
|
||||
dojo.require("dijit._base.focus");
|
||||
dojo.require("dijit._base.place");
|
||||
dojo.require("dijit._base.window");
|
||||
|
||||
dijit.popup = new function(){
|
||||
// summary:
|
||||
// This class is used to show/hide widgets as popups.
|
||||
//
|
||||
|
||||
var stack = [],
|
||||
beginZIndex=1000,
|
||||
idGen = 1;
|
||||
|
||||
this.open = function(/*Object*/ args){
|
||||
// summary:
|
||||
// Popup the widget at the specified position
|
||||
//
|
||||
// args: Object
|
||||
// popup: Widget
|
||||
// widget to display,
|
||||
// parent: Widget
|
||||
// the button etc. that is displaying this popup
|
||||
// around: DomNode
|
||||
// DOM node (typically a button); place popup relative to this node
|
||||
// orient: Object
|
||||
// structure specifying possible positions of popup relative to "around" node
|
||||
// onCancel: Function
|
||||
// callback when user has canceled the popup by
|
||||
// 1. hitting ESC or
|
||||
// 2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
|
||||
// ie: whenever popupWidget.onCancel() is called, args.onCancel is called
|
||||
// onClose: Function
|
||||
// callback whenever this popup is closed
|
||||
// onExecute: Function
|
||||
// callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
|
||||
//
|
||||
// examples:
|
||||
// 1. opening at the mouse position
|
||||
// dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
|
||||
// 2. opening the widget as a dropdown
|
||||
// dijit.popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...} });
|
||||
//
|
||||
// Note that whatever widget called dijit.popup.open() should also listen to it's own _onBlur callback
|
||||
// (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
|
||||
|
||||
var widget = args.popup,
|
||||
orient = args.orient || {'BL':'TL', 'TL':'BL'},
|
||||
around = args.around,
|
||||
id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+idGen++);
|
||||
|
||||
// make wrapper div to hold widget and possibly hold iframe behind it.
|
||||
// we can't attach the iframe as a child of the widget.domNode because
|
||||
// widget.domNode might be a <table>, <ul>, etc.
|
||||
var wrapper = dojo.doc.createElement("div");
|
||||
wrapper.id = id;
|
||||
wrapper.className="dijitPopup";
|
||||
wrapper.style.zIndex = beginZIndex + stack.length;
|
||||
wrapper.style.visibility = "hidden";
|
||||
if(args.parent){
|
||||
wrapper.dijitPopupParent=args.parent.id;
|
||||
}
|
||||
dojo.body().appendChild(wrapper);
|
||||
|
||||
widget.domNode.style.display="";
|
||||
wrapper.appendChild(widget.domNode);
|
||||
|
||||
var iframe = new dijit.BackgroundIframe(wrapper);
|
||||
|
||||
// position the wrapper node
|
||||
var best = around ?
|
||||
dijit.placeOnScreenAroundElement(wrapper, around, orient, widget.orient ? dojo.hitch(widget, "orient") : null) :
|
||||
dijit.placeOnScreen(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR']);
|
||||
|
||||
wrapper.style.visibility = "visible";
|
||||
// TODO: use effects to fade in wrapper
|
||||
|
||||
var handlers = [];
|
||||
|
||||
// Compute the closest ancestor popup that's *not* a child of another popup.
|
||||
// Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
|
||||
function getTopPopup(){
|
||||
for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--);
|
||||
return stack[pi];
|
||||
}
|
||||
|
||||
// provide default escape and tab key handling
|
||||
// (this will work for any widget, not just menu)
|
||||
handlers.push(dojo.connect(wrapper, "onkeypress", this, function(evt){
|
||||
if(evt.keyCode == dojo.keys.ESCAPE && args.onCancel){
|
||||
args.onCancel();
|
||||
}else if(evt.keyCode == dojo.keys.TAB){
|
||||
dojo.stopEvent(evt);
|
||||
var topPopup = getTopPopup();
|
||||
if(topPopup && topPopup.onCancel){
|
||||
topPopup.onCancel();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// watch for cancel/execute events on the popup and notify the caller
|
||||
// (for a menu, "execute" means clicking an item)
|
||||
if(widget.onCancel){
|
||||
handlers.push(dojo.connect(widget, "onCancel", null, args.onCancel));
|
||||
}
|
||||
|
||||
handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", null, function(){
|
||||
var topPopup = getTopPopup();
|
||||
if(topPopup && topPopup.onExecute){
|
||||
topPopup.onExecute();
|
||||
}
|
||||
}));
|
||||
|
||||
stack.push({
|
||||
wrapper: wrapper,
|
||||
iframe: iframe,
|
||||
widget: widget,
|
||||
parent: args.parent,
|
||||
onExecute: args.onExecute,
|
||||
onCancel: args.onCancel,
|
||||
onClose: args.onClose,
|
||||
handlers: handlers
|
||||
});
|
||||
|
||||
if(widget.onOpen){
|
||||
widget.onOpen(best);
|
||||
}
|
||||
|
||||
return best;
|
||||
};
|
||||
|
||||
this.close = function(/*Widget*/ popup){
|
||||
// summary:
|
||||
// Close specified popup and any popups that it parented
|
||||
while(dojo.some(stack, function(elem){return elem.widget == popup;})){
|
||||
var top = stack.pop(),
|
||||
wrapper = top.wrapper,
|
||||
iframe = top.iframe,
|
||||
widget = top.widget,
|
||||
onClose = top.onClose;
|
||||
|
||||
if(widget.onClose){
|
||||
widget.onClose();
|
||||
}
|
||||
dojo.forEach(top.handlers, dojo.disconnect);
|
||||
|
||||
// #2685: check if the widget still has a domNode so ContentPane can change its URL without getting an error
|
||||
if(!widget||!widget.domNode){ return; }
|
||||
dojo.style(widget.domNode, "display", "none");
|
||||
dojo.body().appendChild(widget.domNode);
|
||||
iframe.destroy();
|
||||
dojo._destroyElement(wrapper);
|
||||
|
||||
if(onClose){
|
||||
onClose();
|
||||
}
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
dijit._frames = new function(){
|
||||
// summary: cache of iframes
|
||||
var queue = [];
|
||||
|
||||
this.pop = function(){
|
||||
var iframe;
|
||||
if(queue.length){
|
||||
iframe = queue.pop();
|
||||
iframe.style.display="";
|
||||
}else{
|
||||
if(dojo.isIE){
|
||||
var html="<iframe src='javascript:\"\"'"
|
||||
+ " style='position: absolute; left: 0px; top: 0px;"
|
||||
+ "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
|
||||
iframe = dojo.doc.createElement(html);
|
||||
}else{
|
||||
var iframe = dojo.doc.createElement("iframe");
|
||||
iframe.src = 'javascript:""';
|
||||
iframe.className = "dijitBackgroundIframe";
|
||||
}
|
||||
iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
|
||||
dojo.body().appendChild(iframe);
|
||||
}
|
||||
return iframe;
|
||||
};
|
||||
|
||||
this.push = function(iframe){
|
||||
iframe.style.display="";
|
||||
if(dojo.isIE){
|
||||
iframe.style.removeExpression("width");
|
||||
iframe.style.removeExpression("height");
|
||||
}
|
||||
queue.push(iframe);
|
||||
}
|
||||
}();
|
||||
|
||||
// fill the queue
|
||||
if(dojo.isIE && dojo.isIE < 7){
|
||||
dojo.addOnLoad(function(){
|
||||
var f = dijit._frames;
|
||||
dojo.forEach([f.pop()], f.push);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
dijit.BackgroundIframe = function(/* DomNode */node){
|
||||
// summary:
|
||||
// For IE z-index schenanigans. id attribute is required.
|
||||
//
|
||||
// description:
|
||||
// new dijit.BackgroundIframe(node)
|
||||
// Makes a background iframe as a child of node, that fills
|
||||
// area (and position) of node
|
||||
|
||||
if(!node.id){ throw new Error("no id"); }
|
||||
if((dojo.isIE && dojo.isIE < 7) || (dojo.isFF && dojo.isFF < 3 && dojo.hasClass(dojo.body(), "dijit_a11y"))){
|
||||
var iframe = dijit._frames.pop();
|
||||
node.appendChild(iframe);
|
||||
if(dojo.isIE){
|
||||
iframe.style.setExpression("width", "document.getElementById('" + node.id + "').offsetWidth");
|
||||
iframe.style.setExpression("height", "document.getElementById('" + node.id + "').offsetHeight");
|
||||
}
|
||||
this.iframe = iframe;
|
||||
}
|
||||
};
|
||||
|
||||
dojo.extend(dijit.BackgroundIframe, {
|
||||
destroy: function(){
|
||||
// summary: destroy the iframe
|
||||
if(this.iframe){
|
||||
dijit._frames.push(this.iframe);
|
||||
delete this.iframe;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.scroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.scroll"] = true;
|
||||
dojo.provide("dijit._base.scroll");
|
||||
|
||||
dijit.scrollIntoView = function(/* DomNode */node){
|
||||
// summary
|
||||
// Scroll the passed node into view, if it is not.
|
||||
|
||||
// don't rely on that node.scrollIntoView works just because the function is there
|
||||
// it doesnt work in Konqueror or Opera even though the function is there and probably
|
||||
// not safari either
|
||||
// dont like browser sniffs implementations but sometimes you have to use it
|
||||
if(dojo.isIE){
|
||||
//only call scrollIntoView if there is a scrollbar for this menu,
|
||||
//otherwise, scrollIntoView will scroll the window scrollbar
|
||||
if(dojo.marginBox(node.parentNode).h <= node.parentNode.scrollHeight){ //PORT was getBorderBox
|
||||
node.scrollIntoView(false);
|
||||
}
|
||||
}else if(dojo.isMozilla){
|
||||
node.scrollIntoView(false);
|
||||
}else{
|
||||
var parent = node.parentNode;
|
||||
var parentBottom = parent.scrollTop + dojo.marginBox(parent).h; //PORT was getBorderBox
|
||||
var nodeBottom = node.offsetTop + dojo.marginBox(node).h;
|
||||
if(parentBottom < nodeBottom){
|
||||
parent.scrollTop += (nodeBottom - parentBottom);
|
||||
}else if(parent.scrollTop > node.offsetTop){
|
||||
parent.scrollTop -= (parent.scrollTop - node.offsetTop);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.sniff"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.sniff"] = true;
|
||||
dojo.provide("dijit._base.sniff");
|
||||
|
||||
// ported from dojo.html.applyBrowserClass (style.js)
|
||||
|
||||
// summary:
|
||||
// Applies pre-set class names based on browser & version to the
|
||||
// top-level HTML node. Simply doing a require on this module will
|
||||
// establish this CSS. Modified version of Morris' CSS hack.
|
||||
(function(){
|
||||
var d = dojo;
|
||||
var ie = d.isIE;
|
||||
var opera = d.isOpera;
|
||||
var maj = Math.floor;
|
||||
var classes = {
|
||||
dj_ie: ie,
|
||||
// dj_ie55: ie == 5.5,
|
||||
dj_ie6: maj(ie) == 6,
|
||||
dj_ie7: maj(ie) == 7,
|
||||
dj_iequirks: ie && d.isQuirks,
|
||||
// NOTE: Opera not supported by dijit
|
||||
dj_opera: opera,
|
||||
dj_opera8: maj(opera) == 8,
|
||||
dj_opera9: maj(opera) == 9,
|
||||
dj_khtml: d.isKhtml,
|
||||
dj_safari: d.isSafari,
|
||||
dj_gecko: d.isMozilla
|
||||
}; // no dojo unsupported browsers
|
||||
|
||||
for(var p in classes){
|
||||
if(classes[p]){
|
||||
var html = dojo.doc.documentElement; //TODO browser-specific DOM magic needed?
|
||||
if(html.className){
|
||||
html.className += " " + p;
|
||||
}else{
|
||||
html.className = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.typematic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.typematic"] = true;
|
||||
dojo.provide("dijit._base.typematic");
|
||||
|
||||
dijit.typematic = {
|
||||
// summary:
|
||||
// These functions are used to repetitively call a user specified callback
|
||||
// method when a specific key or mouse click over a specific DOM node is
|
||||
// held down for a specific amount of time.
|
||||
// Only 1 such event is allowed to occur on the browser page at 1 time.
|
||||
|
||||
_fireEventAndReload: function(){
|
||||
this._timer = null;
|
||||
this._callback(++this._count, this._node, this._evt);
|
||||
this._currentTimeout = (this._currentTimeout < 0) ? this._initialDelay : ((this._subsequentDelay > 1) ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay));
|
||||
this._timer = setTimeout(dojo.hitch(this, "_fireEventAndReload"), this._currentTimeout);
|
||||
},
|
||||
|
||||
trigger: function(/*Event*/ evt, /* Object */ _this, /*DOMNode*/ node, /* Function */ callback, /* Object */ obj, /* Number */ subsequentDelay, /* Number */ initialDelay){
|
||||
// summary:
|
||||
// Start a timed, repeating callback sequence.
|
||||
// If already started, the function call is ignored.
|
||||
// This method is not normally called by the user but can be
|
||||
// when the normal listener code is insufficient.
|
||||
// Parameters:
|
||||
// evt: key or mouse event object to pass to the user callback
|
||||
// _this: pointer to the user's widget space.
|
||||
// node: the DOM node object to pass the the callback function
|
||||
// callback: function to call until the sequence is stopped called with 3 parameters:
|
||||
// count: integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
|
||||
// node: the DOM node object passed in
|
||||
// evt: key or mouse event object
|
||||
// obj: user space object used to uniquely identify each typematic sequence
|
||||
// subsequentDelay: if > 1, the number of milliseconds until the 3->n events occur
|
||||
// or else the fractional time multiplier for the next event's delay, default=0.9
|
||||
// initialDelay: the number of milliseconds until the 2nd event occurs, default=500ms
|
||||
if(obj != this._obj){
|
||||
this.stop();
|
||||
this._initialDelay = initialDelay || 500;
|
||||
this._subsequentDelay = subsequentDelay || 0.90;
|
||||
this._obj = obj;
|
||||
this._evt = evt;
|
||||
this._node = node;
|
||||
this._currentTimeout = -1;
|
||||
this._count = -1;
|
||||
this._callback = dojo.hitch(_this, callback);
|
||||
this._fireEventAndReload();
|
||||
}
|
||||
},
|
||||
|
||||
stop: function(){
|
||||
// summary:
|
||||
// Stop an ongoing timed, repeating callback sequence.
|
||||
if(this._timer){
|
||||
clearTimeout(this._timer);
|
||||
this._timer = null;
|
||||
}
|
||||
if(this._obj){
|
||||
this._callback(-1, this._node, this._evt);
|
||||
this._obj = null;
|
||||
}
|
||||
},
|
||||
|
||||
addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
|
||||
// summary: Start listening for a specific typematic key.
|
||||
// keyObject: an object defining the key to listen for.
|
||||
// key: (mandatory) the keyCode (number) or character (string) to listen for.
|
||||
// ctrlKey: desired ctrl key state to initiate the calback sequence:
|
||||
// pressed (true)
|
||||
// released (false)
|
||||
// either (unspecified)
|
||||
// altKey: same as ctrlKey but for the alt key
|
||||
// shiftKey: same as ctrlKey but for the shift key
|
||||
// See the trigger method for other parameters.
|
||||
// Returns an array of dojo.connect handles
|
||||
return [
|
||||
dojo.connect(node, "onkeypress", this, function(evt){
|
||||
if(evt.keyCode == keyObject.keyCode && (!keyObject.charCode || keyObject.charCode == evt.charCode) &&
|
||||
(keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
|
||||
(keyObject.altKey === undefined || keyObject.altKey == evt.ctrlKey) &&
|
||||
(keyObject.shiftKey === undefined || keyObject.shiftKey == evt.ctrlKey)){
|
||||
dojo.stopEvent(evt);
|
||||
dijit.typematic.trigger(keyObject, _this, node, callback, keyObject, subsequentDelay, initialDelay);
|
||||
}else if(dijit.typematic._obj == keyObject){
|
||||
dijit.typematic.stop();
|
||||
}
|
||||
}),
|
||||
dojo.connect(node, "onkeyup", this, function(evt){
|
||||
if(dijit.typematic._obj == keyObject){
|
||||
dijit.typematic.stop();
|
||||
}
|
||||
})
|
||||
];
|
||||
},
|
||||
|
||||
addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
|
||||
// summary: Start listening for a typematic mouse click.
|
||||
// See the trigger method for other parameters.
|
||||
// Returns an array of dojo.connect handles
|
||||
var dc = dojo.connect;
|
||||
return [
|
||||
dc(node, "mousedown", this, function(evt){
|
||||
dojo.stopEvent(evt);
|
||||
dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay);
|
||||
}),
|
||||
dc(node, "mouseup", this, function(evt){
|
||||
dojo.stopEvent(evt);
|
||||
dijit.typematic.stop();
|
||||
}),
|
||||
dc(node, "mouseout", this, function(evt){
|
||||
dojo.stopEvent(evt);
|
||||
dijit.typematic.stop();
|
||||
}),
|
||||
dc(node, "mousemove", this, function(evt){
|
||||
dojo.stopEvent(evt);
|
||||
}),
|
||||
dc(node, "dblclick", this, function(evt){
|
||||
dojo.stopEvent(evt);
|
||||
if(dojo.isIE){
|
||||
dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay);
|
||||
setTimeout(dijit.typematic.stop, 50);
|
||||
}
|
||||
})
|
||||
];
|
||||
},
|
||||
|
||||
addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
|
||||
// summary: Start listening for a specific typematic key and mouseclick.
|
||||
// This is a thin wrapper to addKeyListener and addMouseListener.
|
||||
// mouseNode: the DOM node object to listen on for mouse events.
|
||||
// keyNode: the DOM node object to listen on for key events.
|
||||
// See the addMouseListener and addKeyListener methods for other parameters.
|
||||
// Returns an array of dojo.connect handles
|
||||
return this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay).concat(
|
||||
this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.wai"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.wai"] = true;
|
||||
dojo.provide("dijit._base.wai");
|
||||
|
||||
dijit.wai = {
|
||||
onload: function(){
|
||||
// summary:
|
||||
// Function that detects if we are in high-contrast mode or not,
|
||||
// and sets up a timer to periodically confirm the value.
|
||||
// figure out the background-image style property
|
||||
// and apply that to the image.src property.
|
||||
// description:
|
||||
// This must be a named function and not an anonymous
|
||||
// function, so that the widget parsing code can make sure it
|
||||
// registers its onload function after this function.
|
||||
// DO NOT USE "this" within this function.
|
||||
|
||||
// create div for testing if high contrast mode is on or images are turned off
|
||||
var div = document.createElement("div");
|
||||
div.id = "a11yTestNode";
|
||||
div.style.cssText = 'border: 1px solid;'
|
||||
+ 'border-color:red green;'
|
||||
+ 'position: absolute;'
|
||||
+ 'height: 5px;'
|
||||
+ 'top: -999px;'
|
||||
+ 'background-image: url("' + dojo.moduleUrl("dijit", "form/templates/blank.gif") + '");';
|
||||
dojo.body().appendChild(div);
|
||||
|
||||
// test it
|
||||
function check(){
|
||||
var cs = dojo.getComputedStyle(div);
|
||||
if(cs){
|
||||
var bkImg = cs.backgroundImage;
|
||||
var needsA11y = (cs.borderTopColor==cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
|
||||
dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y");
|
||||
}
|
||||
}
|
||||
check();
|
||||
if(dojo.isIE){
|
||||
setInterval(check, 4000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Test if computer is in high contrast mode.
|
||||
// Make sure the a11y test runs first, before widgets are instantiated.
|
||||
if(dojo.isIE || dojo.isMoz){ // NOTE: checking in Safari messes things up
|
||||
dojo._loaders.unshift(dijit.wai.onload);
|
||||
}
|
||||
|
||||
dojo.mixin(dijit,
|
||||
{
|
||||
hasWaiRole: function(/*Element*/ elem){
|
||||
// Summary: Return true if elem has a role attribute and false if not.
|
||||
if(elem.hasAttribute){
|
||||
return elem.hasAttribute("role");
|
||||
}else{
|
||||
return elem.getAttribute("role") ? true : false;
|
||||
}
|
||||
},
|
||||
|
||||
getWaiRole: function(/*Element*/ elem){
|
||||
// Summary: Return the role of elem or an empty string if
|
||||
// elem does not have a role.
|
||||
var value = elem.getAttribute("role");
|
||||
if(value){
|
||||
var prefixEnd = value.indexOf(":");
|
||||
return prefixEnd == -1 ? value : value.substring(prefixEnd+1);
|
||||
}else{
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
setWaiRole: function(/*Element*/ elem, /*String*/ role){
|
||||
// Summary: Set the role on elem. On Firefox 2 and below, "wairole:" is
|
||||
// prepended to the provided role value.
|
||||
if(dojo.isFF && dojo.isFF < 3){
|
||||
elem.setAttribute("role", "wairole:"+role);
|
||||
}else{
|
||||
elem.setAttribute("role", role);
|
||||
}
|
||||
},
|
||||
|
||||
removeWaiRole: function(/*Element*/ elem){
|
||||
// Summary: Removes the role attribute from elem.
|
||||
elem.removeAttribute("role");
|
||||
},
|
||||
|
||||
hasWaiState: function(/*Element*/ elem, /*String*/ state){
|
||||
// Summary: Return true if elem has a value for the given state and
|
||||
// false if it does not.
|
||||
// On Firefox 2 and below, we check for an attribute in namespace
|
||||
// "http://www.w3.org/2005/07/aaa" with a name of the given state.
|
||||
// On all other browsers, we check for an attribute called
|
||||
// "aria-"+state.
|
||||
if(dojo.isFF && dojo.isFF < 3){
|
||||
return elem.hasAttributeNS("http://www.w3.org/2005/07/aaa", state);
|
||||
}else{
|
||||
if(elem.hasAttribute){
|
||||
return elem.hasAttribute("aria-"+state);
|
||||
}else{
|
||||
return elem.getAttribute("aria-"+state) ? true : false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getWaiState: function(/*Element*/ elem, /*String*/ state){
|
||||
// Summary: Return the value of the requested state on elem
|
||||
// or an empty string if elem has no value for state.
|
||||
// On Firefox 2 and below, we check for an attribute in namespace
|
||||
// "http://www.w3.org/2005/07/aaa" with a name of the given state.
|
||||
// On all other browsers, we check for an attribute called
|
||||
// "aria-"+state.
|
||||
if(dojo.isFF && dojo.isFF < 3){
|
||||
return elem.getAttributeNS("http://www.w3.org/2005/07/aaa", state);
|
||||
}else{
|
||||
var value = elem.getAttribute("aria-"+state);
|
||||
return value ? value : "";
|
||||
}
|
||||
},
|
||||
|
||||
setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
|
||||
// Summary: Set state on elem to value.
|
||||
// On Firefox 2 and below, we set an attribute in namespace
|
||||
// "http://www.w3.org/2005/07/aaa" with a name of the given state.
|
||||
// On all other browsers, we set an attribute called
|
||||
// "aria-"+state.
|
||||
if(dojo.isFF && dojo.isFF < 3){
|
||||
elem.setAttributeNS("http://www.w3.org/2005/07/aaa",
|
||||
"aaa:"+state, value);
|
||||
}else{
|
||||
elem.setAttribute("aria-"+state, value);
|
||||
}
|
||||
},
|
||||
|
||||
removeWaiState: function(/*Element*/ elem, /*String*/ state){
|
||||
// Summary: Removes the given state from elem.
|
||||
// On Firefox 2 and below, we remove the attribute in namespace
|
||||
// "http://www.w3.org/2005/07/aaa" with a name of the given state.
|
||||
// On all other browsers, we remove the attribute called
|
||||
// "aria-"+state.
|
||||
if(dojo.isFF && dojo.isFF < 3){
|
||||
elem.removeAttributeNS("http://www.w3.org/2005/07/aaa", state);
|
||||
}else{
|
||||
elem.removeAttribute("aria-"+state);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._base.window"] = true;
|
||||
dojo.provide("dijit._base.window");
|
||||
|
||||
dijit.getDocumentWindow = function(doc){
|
||||
// summary
|
||||
// Get window object associated with document doc
|
||||
|
||||
// With Safari, there is not way to retrieve the window from the document, so we must fix it.
|
||||
if(dojo.isSafari && !doc._parentWindow){
|
||||
/*
|
||||
This is a Safari specific function that fix the reference to the parent
|
||||
window from the document object.
|
||||
*/
|
||||
var fix=function(win){
|
||||
win.document._parentWindow=win;
|
||||
for(var i=0; i<win.frames.length; i++){
|
||||
fix(win.frames[i]);
|
||||
}
|
||||
}
|
||||
fix(window.top);
|
||||
}
|
||||
|
||||
//In some IE versions (at least 6.0), document.parentWindow does not return a
|
||||
//reference to the real window object (maybe a copy), so we must fix it as well
|
||||
//We use IE specific execScript to attach the real window reference to
|
||||
//document._parentWindow for later use
|
||||
if(dojo.isIE && window !== document.parentWindow && !doc._parentWindow){
|
||||
/*
|
||||
In IE 6, only the variable "window" can be used to connect events (others
|
||||
may be only copies).
|
||||
*/
|
||||
doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
|
||||
//to prevent memory leak, unset it after use
|
||||
//another possibility is to add an onUnload handler which seems overkill to me (liucougar)
|
||||
var win = doc._parentWindow;
|
||||
doc._parentWindow = null;
|
||||
return win; // Window
|
||||
}
|
||||
|
||||
return doc._parentWindow || doc.parentWindow || doc.defaultView; // Window
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,91 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor._Plugin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor._Plugin"] = true;
|
||||
dojo.provide("dijit._editor._Plugin");
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit.Editor");
|
||||
dojo.require("dijit.form.Button");
|
||||
|
||||
dojo.declare("dijit._editor._Plugin", null, {
|
||||
// summary
|
||||
// This represents a "plugin" to the editor, which is basically
|
||||
// a single button on the Toolbar and some associated code
|
||||
constructor: function(/*Object?*/args, /*DomNode?*/node){
|
||||
if(args){
|
||||
dojo.mixin(this, args);
|
||||
}
|
||||
},
|
||||
|
||||
editor: null,
|
||||
iconClassPrefix: "dijitEditorIcon",
|
||||
button: null,
|
||||
queryCommand: null,
|
||||
command: "",
|
||||
commandArg: null,
|
||||
useDefaultCommand: true,
|
||||
buttonClass: dijit.form.Button,
|
||||
updateInterval: 200, // only allow updates every two tenths of a second
|
||||
_initButton: function(){
|
||||
if(this.command.length){
|
||||
var label = this.editor.commands[this.command];
|
||||
var className = "dijitEditorIcon "+this.iconClassPrefix + this.command.charAt(0).toUpperCase() + this.command.substr(1);
|
||||
if(!this.button){
|
||||
var props = {
|
||||
label: label,
|
||||
showLabel: false,
|
||||
iconClass: className,
|
||||
dropDown: this.dropDown
|
||||
};
|
||||
this.button = new this.buttonClass(props);
|
||||
}
|
||||
}
|
||||
},
|
||||
updateState: function(){
|
||||
var _e = this.editor;
|
||||
var _c = this.command;
|
||||
if(!_e){ return; }
|
||||
if(!_e.isLoaded){ return; }
|
||||
if(!_c.length){ return; }
|
||||
if(this.button){
|
||||
try{
|
||||
var enabled = _e.queryCommandEnabled(_c);
|
||||
this.button.setDisabled(!enabled);
|
||||
if(this.button.setChecked){
|
||||
this.button.setChecked(_e.queryCommandState(_c));
|
||||
}
|
||||
}catch(e){
|
||||
console.debug(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
setEditor: function(/*Widget*/editor){
|
||||
// FIXME: detatch from previous editor!!
|
||||
this.editor = editor;
|
||||
|
||||
// FIXME: prevent creating this if we don't need to (i.e., editor can't handle our command)
|
||||
this._initButton();
|
||||
|
||||
// FIXME: wire up editor to button here!
|
||||
if( (this.command.length) &&
|
||||
(!this.editor.queryCommandAvailable(this.command))
|
||||
){
|
||||
// console.debug("hiding:", this.command);
|
||||
if(this.button){
|
||||
this.button.domNode.style.display = "none";
|
||||
}
|
||||
}
|
||||
if(this.button && this.useDefaultCommand){
|
||||
dojo.connect(this.button, "onClick",
|
||||
dojo.hitch(this.editor, "execCommand", this.command, this.commandArg)
|
||||
);
|
||||
}
|
||||
dojo.connect(this.editor, "onNormalizedDisplayChanged", this, "updateState");
|
||||
},
|
||||
setToolbar: function(/*Widget*/toolbar){
|
||||
if(this.button){
|
||||
toolbar.addChild(this.button);
|
||||
}
|
||||
// console.debug("adding", this.button, "to:", toolbar);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
({"1": "xx-small", "2": "x-small", "formatBlock": "Format", "monospaced": "monospaced", "3": "small", "4": "medium", "5": "large", "6": "x-large", "7": "xx-large", "fantasy": "fantasy", "serif": "serif", "p": "Paragraph", "pre": "Pre-formatted", "sans-serif": "sans-serif", "fontName": "Font", "h1": "Heading", "h2": "Subheading", "h3": "Sub-subheading", "fontSize": "Size", "cursive": "cursive"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Set", "text": "Text:", "title": "Link URL", "url": "URL:", "urlInvalidMessage": "Invalid URL. Enter a full URL like 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Remove Format", "copy": "Copy", "paste": "Paste", "selectAll": "Select All", "insertOrderedList": "Numbered List", "insertTable": "Insert/Edit Table", "underline": "Underline", "foreColor": "Foreground Color", "htmlToggle": "HTML Source", "formatBlock": "Paragraph Style", "insertHorizontalRule": "Horizontal Rule", "delete": "Delete", "appleKey": "⌘${0}", "insertUnorderedList": "Bullet List", "tableProp": "Table Property", "insertImage": "Insert Image", "superscript": "Superscript", "subscript": "Subscript", "createLink": "Create Link", "undo": "Undo", "italic": "Italic", "fontName": "Font Name", "justifyLeft": "Align Left", "unlink": "Remove Link", "toggleTableBorder": "Toggle Table Border", "ctrlKey": "ctrl+${0}", "fontSize": "Font Size", "indent": "Indent", "redo": "Redo", "strikethrough": "Strikethrough", "justifyFull": "Justify", "justifyCenter": "Align Center", "hiliteColor": "Background Color", "deleteTable": "Delete Table", "outdent": "Outdent", "cut": "Cut", "plainFormatBlock": "Paragraph Style", "bold": "Bold", "systemShortcutFF": "The \"${0}\" action is only available in Mozilla Firefox using a keyboard shortcut. Use ${1}.", "justifyRight": "Align Right"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Nastavit", "text": "Text:", "title": "Adresa URL odkazu", "url": "Adresa URL:", "urlInvalidMessage": "Neplatná adresa URL. Zadejte úplnou adresu URL ve tvaru 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Odebrat formát", "copy": "Kopírovat", "paste": "Vložit", "selectAll": "Vybrat vše", "insertOrderedList": "Číslovaný seznam", "insertTable": "Vložit/upravit tabulku", "underline": "Podtržení", "foreColor": "Barva popředí", "htmlToggle": "Zdroj HTML", "formatBlock": "Styl odstavce", "insertHorizontalRule": "Vodorovné pravítko", "delete": "Odstranit", "insertUnorderedList": "Seznam s odrážkami", "tableProp": "Vlastnost tabulky", "insertImage": "Vložit obraz", "superscript": "Horní index", "subscript": "Dolní index", "createLink": "Vytvořit odkaz", "undo": "Zpět", "italic": "Kurzíva", "fontName": "Název písma", "justifyLeft": "Zarovnat vlevo", "unlink": "Odebrat odkaz", "toggleTableBorder": "Přepnout ohraničení tabulky", "fontSize": "Velikost písma", "indent": "Odsadit", "redo": "Opakovat", "strikethrough": "Přeškrtnutí", "justifyFull": "Do bloku", "justifyCenter": "Zarovnat na střed", "hiliteColor": "Barva pozadí", "deleteTable": "Odstranit tabulku", "outdent": "Předsadit", "cut": "Vyjmout", "plainFormatBlock": "Styl odstavce", "bold": "Tučné", "systemShortcutFF": "Akce \"${0}\" je k dispozici pouze v prohlížeči Mozilla Firefox při použití klávesové zkratky. Použijte ${1}.", "justifyRight": "Zarovnat vpravo", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Festlegen", "text": "Text:", "title": "Link-URL", "url": "URL:", "urlInvalidMessage": "Ungültiger URL. Geben Sie einen vollständigen URL ein. Beispiel: 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Formatierung entfernen", "copy": "Kopieren", "paste": "Einfügen", "selectAll": "Alles auswählen", "insertOrderedList": "Nummerierte Liste", "insertTable": "Tabelle einfügen/bearbeiten", "underline": "Unterstrichen", "foreColor": "Vordergrundfarbe", "htmlToggle": "HTML-Quelltext", "formatBlock": "Absatzstil", "insertHorizontalRule": "Horizontaler Strich", "delete": "Löschen", "insertUnorderedList": "Listenpunkte", "tableProp": "Tabelleneigenschaft", "insertImage": "Grafik einfügen", "superscript": "Hochgestellt", "subscript": "Tiefgestellt", "createLink": "Link erstellen", "undo": "Rückgängig", "italic": "Kursiv", "fontName": "Schriftartname", "justifyLeft": "Linksbündig", "unlink": "Link entfernen", "toggleTableBorder": "Tabellenumrandung ein-/ausschalten", "ctrlKey": "Strg+${0}", "fontSize": "Schriftgröße", "indent": "Einrücken", "redo": "Wiederherstellen", "strikethrough": "Durchgestrichen", "justifyFull": "Blocksatz", "justifyCenter": "Zentrieren", "hiliteColor": "Hintergrundfarbe", "deleteTable": "Tabelle löschen", "outdent": "Ausrücken", "cut": "Ausschneiden", "plainFormatBlock": "Absatzstil", "bold": "Fett", "systemShortcutFF": "Die Aktion \"${0}\" ist in Mozilla Firefox nur über einen Tastaturkurzbefehl verfügbar. Verwenden Sie ${1}.", "justifyRight": "Rechtsbündig", "appleKey": "⌘${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Establecer", "text": "Texto:", "title": "Enlazar URL", "url": "URL:", "urlInvalidMessage": "URL no válido. Especifique un URL completo como 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Eliminar formato", "copy": "Copiar", "paste": "Pegar", "selectAll": "Seleccionar todo", "insertOrderedList": "Lista numerada", "insertTable": "Insertar/Editar tabla", "underline": "Subrayado", "foreColor": "Color de primer plano", "htmlToggle": "Fuente HTML", "formatBlock": "Estilo de párrafo", "insertHorizontalRule": "Regla horizontal", "delete": "Suprimir", "insertUnorderedList": "Lista con viñetas", "tableProp": "Propiedad de tabla", "insertImage": "Insertar imagen", "superscript": "Superíndice", "subscript": "Subíndice", "createLink": "Crear enlace", "undo": "Deshacer", "italic": "Cursiva", "fontName": "Nombre de font", "justifyLeft": "Alinear izquierda", "unlink": "Eliminar enlace", "toggleTableBorder": "Conmutar borde de tabla", "ctrlKey": "Control+${0}", "fontSize": "Tamaño de font", "indent": "Sangría", "redo": "Rehacer", "strikethrough": "Tachado", "justifyFull": "Justificar", "justifyCenter": "Alinear centro", "hiliteColor": "Color de segundo plano", "deleteTable": "Suprimir tabla", "outdent": "Anular sangría", "cut": "Cortar", "plainFormatBlock": "Estilo de párrafo", "bold": "Negrita", "systemShortcutFF": "La acción \"${0}\" sólo está disponible en Mozilla Firefox mediante un atajo de teclado. Utilice ${1}.", "justifyRight": "Alinear derecha", "appleKey": "⌘${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Définir", "text": "Texte :", "title": "URL du lien", "url": "URL :", "urlInvalidMessage": "Adresse URL non valide. Entrez une adresse URL complète de type 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Supprimer la mise en forme", "copy": "Copier", "paste": "Coller", "selectAll": "Sélectionner tout", "insertOrderedList": "Liste numérotée", "insertTable": "Insérer/Modifier un tableau", "underline": "Souligner", "foreColor": "Couleur d'avant-plan", "htmlToggle": "Source HTML", "formatBlock": "Style de paragraphe", "insertHorizontalRule": "Règle horizontale", "delete": "Supprimer", "insertUnorderedList": "Liste à puces", "tableProp": "Propriété du tableau", "insertImage": "Insérer une image", "superscript": "Exposant", "subscript": "Indice", "createLink": "Créer un lien", "undo": "Annuler", "italic": "Italique", "fontName": "Nom de police", "justifyLeft": "Aligner à gauche", "unlink": "Supprimer le lien", "toggleTableBorder": "Afficher/Masquer la bordure du tableau", "fontSize": "Taille de police", "indent": "Retrait", "redo": "Rétablir", "strikethrough": "Barrer", "justifyFull": "Justifier", "justifyCenter": "Aligner au centre", "hiliteColor": "Couleur d'arrière-plan", "deleteTable": "Supprimer le tableau", "outdent": "Retrait négatif", "cut": "Couper", "plainFormatBlock": "Style de paragraphe", "bold": "Gras", "systemShortcutFF": "L'action \"${0}\" est disponible dans Mozilla Firefox uniquement, par le biais d'un raccourci-clavier. Utilisez ${1}.", "justifyRight": "Aligner à droite", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Beállítás", "text": "Szöveg:", "title": "Hivatkozás URL címe", "url": "URL:", "urlInvalidMessage": "Érvénytelen URL cím. Adjon meg teljes URL címet, például: 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Formázás eltávolítása", "copy": "Másolás", "paste": "Beillesztés", "selectAll": "Összes kijelölése", "insertOrderedList": "Számozott lista", "insertTable": "Táblázat beszúrása/szerkesztése", "underline": "Aláhúzott", "foreColor": "Előtérszín", "htmlToggle": "HTML forrás", "formatBlock": "Bekezdés stílusa", "insertHorizontalRule": "Vízszintes vonalzó", "delete": "Törlés", "insertUnorderedList": "Felsorolásjeles lista", "tableProp": "Táblázat tulajdonságai", "insertImage": "Kép beszúrása", "superscript": "Felső index", "subscript": "Alsó index", "createLink": "Hivatkozás létrehozása", "undo": "Visszavonás", "italic": "Dőlt", "fontName": "Betűtípus", "justifyLeft": "Balra igazítás", "unlink": "Hivatkozás eltávolítása", "toggleTableBorder": "Táblázatszegély ki-/bekapcsolása", "fontSize": "Betűméret", "indent": "Behúzás", "redo": "Újra", "strikethrough": "Áthúzott", "justifyFull": "Igazítás", "justifyCenter": "Középre igazítás", "hiliteColor": "Háttérszín", "deleteTable": "Táblázat törlése", "outdent": "Negatív behúzás", "cut": "Kivágás", "plainFormatBlock": "Bekezdés stílusa", "bold": "Félkövér", "systemShortcutFF": "A(z) \"${0}\" művelet csak Mozilla Firefox böngészőben érhető el billentyűparancs használatával. Használja a következőt: ${1}.", "justifyRight": "Jobbra igazítás", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Imposta", "text": "Testo:", "title": "URL di collegamento", "url": "URL:", "urlInvalidMessage": "URL non valido. Immettere un URL completo come nel seguente esempio: 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Rimuovi formato", "copy": "Copia", "paste": "Incolla", "selectAll": "Seleziona tutto", "insertOrderedList": "Elenco numerato", "insertTable": "Inserisci/Modifica tabella", "underline": "Sottolineato", "foreColor": "Colore primo piano", "htmlToggle": "Origine HTML", "formatBlock": "Stile paragrafo", "insertHorizontalRule": "Righello orizzontale", "delete": "Elimina", "insertUnorderedList": "Elenco puntato", "tableProp": "Proprietà tabella", "insertImage": "Inserisci immagine", "superscript": "Apice", "subscript": "Pedice", "createLink": "Crea collegamento", "undo": "Annulla", "italic": "Corsivo", "fontName": "Nome carattere", "justifyLeft": "Allinea a sinistra", "unlink": "Rimuovi collegamento", "toggleTableBorder": "Mostra/Nascondi margine tabella", "fontSize": "Dimensione carattere", "indent": "Rientra", "redo": "Ripristina", "strikethrough": "Barrato", "justifyFull": "Giustifica", "justifyCenter": "Allinea al centro", "hiliteColor": "Colore sfondo", "deleteTable": "Elimina tabella", "outdent": "Rimuovi rientro", "cut": "Taglia", "plainFormatBlock": "Stile paragrafo", "bold": "Grassetto", "systemShortcutFF": "L'azione \"${0}\" è disponibile solo in Mozilla Firefox tramite tasti di scelta rapida. Utilizzare ${1}.", "justifyRight": "Allinea a destra", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "設定", "text": "テキスト:", "title": "リンク URL", "url": "URL:", "urlInvalidMessage": "無効な URL です。完全な URL (例えば、http://www.dojotoolkit.org) を入力してください。"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "形式の除去", "copy": "コピー", "paste": "貼り付け", "selectAll": "すべて選択", "insertOrderedList": "番号付きリスト", "insertTable": "テーブルの挿入/編集", "underline": "下線", "foreColor": "前景色", "htmlToggle": "HTML ソース", "formatBlock": "段落スタイル", "insertHorizontalRule": "水平罫線", "delete": "削除", "insertUnorderedList": "黒丸付きリスト", "tableProp": "テーブル・プロパティー", "insertImage": "イメージの挿入", "superscript": "上付き文字", "subscript": "下付き文字", "createLink": "リンクの作成", "undo": "取り消し", "italic": "イタリック", "fontName": "フォント名", "justifyLeft": "左揃え", "unlink": "リンクの除去", "toggleTableBorder": "テーブル・ボーダーの切り替え", "fontSize": "フォント・サイズ", "indent": "インデント", "redo": "再実行", "strikethrough": "取り消し線", "justifyFull": "行末揃え", "justifyCenter": "中央揃え", "hiliteColor": "背景色", "deleteTable": "テーブルの削除", "outdent": "アウトデント", "cut": "切り取り", "plainFormatBlock": "段落スタイル", "bold": "太字", "systemShortcutFF": "\"${0}\" アクションは、キーボード・ショートカットを使用して Mozilla Firefox でのみ使用できます。${1} を使用してください。", "justifyRight": "右揃え", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "설정", "text": "텍스트:", "title": "URL 링크", "url": "URL:", "urlInvalidMessage": "유효하지 않은 URL입니다. 'http://www.dojotoolkit.org'와 같이 전체 URL을 입력하십시오. "})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "형식 제거", "copy": "복사", "paste": "붙여넣기", "selectAll": "모두 선택", "insertOrderedList": "번호 목록", "insertTable": "테이블 삽입/편집", "underline": "밑줄", "foreColor": "전경색", "htmlToggle": "HTML 소스", "formatBlock": "단락 양식", "insertHorizontalRule": "수평 자", "delete": "삭제", "insertUnorderedList": "글머리표 목록", "tableProp": "테이블 특성", "insertImage": "이미지 삽입", "superscript": "위첨자", "subscript": "아래첨자", "createLink": "링크 작성", "undo": "실행 취소", "italic": "이탤릭체", "fontName": "글꼴 이름", "justifyLeft": "왼쪽 맞춤", "unlink": "링크 제거", "toggleTableBorder": "토글 테이블 경계", "fontSize": "글꼴 크기", "indent": "들여쓰기", "redo": "다시 실행", "strikethrough": "취소선", "justifyFull": "양쪽 맞춤", "justifyCenter": "가운데 맞춤", "hiliteColor": "배경색", "deleteTable": "테이블 삭제", "outdent": "내어쓰기", "cut": "잘라내기", "plainFormatBlock": "단락 양식", "bold": "굵은체", "systemShortcutFF": "\"${0}\" 조치는 키보드 바로 가기를 사용하는 Mozilla Firefox에서만 사용 가능합니다. ${1} 사용.", "justifyRight": "오른쪽 맞춤", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Ustaw", "text": "Tekst:", "title": "Adres URL odsyłacza", "url": "Adres URL:", "urlInvalidMessage": "Nieprawidłowy adres URL. Wprowadź pełny adres URL, na przykład http://www.dojotoolkit.org."})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Usuń formatowanie", "copy": "Kopiuj", "paste": "Wklej", "selectAll": "Wybierz wszystko", "insertOrderedList": "Lista numerowana", "insertTable": "Wstaw/edytuj tabelę", "underline": "Podkreślenie", "foreColor": "Kolor pierwszego planu", "htmlToggle": "Źródło HTML", "formatBlock": "Styl akapitu", "insertHorizontalRule": "Linia pozioma", "delete": "Usuń", "insertUnorderedList": "Lista wypunktowana", "tableProp": "Właściwość tabeli", "insertImage": "Wstaw obraz", "superscript": "Indeks górny", "subscript": "Indeks dolny", "createLink": "Utwórz odsyłacz", "undo": "Cofnij", "italic": "Kursywa", "fontName": "Nazwa czcionki", "justifyLeft": "Wyrównaj do lewej", "unlink": "Usuń odsyłacz", "toggleTableBorder": "Przełącz ramkę tabeli", "fontSize": "Wielkość czcionki", "indent": "Wcięcie", "redo": "Przywróć", "strikethrough": "Przekreślenie", "justifyFull": "Wyrównaj do lewej i prawej", "justifyCenter": "Wyrównaj do środka", "hiliteColor": "Kolor tła", "deleteTable": "Usuń tabelę", "outdent": "Usuń wcięcie", "cut": "Wytnij", "plainFormatBlock": "Styl akapitu", "bold": "Pogrubienie", "systemShortcutFF": "Działanie \"${0}\" jest dostępne w przeglądarce Mozilla Firefox wyłącznie za pomocą skrótu klawiaturowego. Użyj ${1}.", "justifyRight": "Wyrównaj do prawej", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Definir\n", "text": "Texto:\n", "title": "Vincular URL", "url": "URL:", "urlInvalidMessage": "URL inválida. Digite uma URL completa, como 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Remover Formato", "copy": "Copiar", "paste": "Colar", "selectAll": "Selecionar Todos", "insertOrderedList": "Lista Numerada", "insertTable": "Inserir/Editar Tabela", "underline": "Sublinhado", "foreColor": "Cor do Primeiro Plano", "htmlToggle": "Origem HTML", "formatBlock": "Estilo de Parágrafo", "insertHorizontalRule": "Régua Horizontal", "delete": "Excluir ", "insertUnorderedList": "Lista com Marcadores", "tableProp": "Propriedade da Tabela", "insertImage": "Inserir Imagem", "superscript": "Sobrescrito", "subscript": "Subscrito", "createLink": "Criar Link", "undo": "Desfazer", "italic": "Itálico", "fontName": "Nome da Fonte", "justifyLeft": "Alinhar pela Esquerda", "unlink": "Remover Link", "toggleTableBorder": "Alternar Moldura da Tabela", "fontSize": "Tamanho da Fonte", "indent": "Recuar", "redo": "Refazer", "strikethrough": "Tachado", "justifyFull": "Justificar", "justifyCenter": "Alinhar pelo Centro", "hiliteColor": "Cor de segundo plano", "deleteTable": "Excluir Tabela", "outdent": "Não-chanfrado", "cut": "Recortar", "plainFormatBlock": "Estilo de Parágrafo", "bold": "Negrito", "systemShortcutFF": "A ação \"${0}\" está disponível apenas no Mozilla Firefox utilizando um atalho do teclado. Utilize ${1}.", "justifyRight": "Alinhar pela Direita", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "Задать", "text": "Текст:", "title": "URL ссылки", "url": "URL:", "urlInvalidMessage": "Недопустимый адрес URL. Укажите полный URL, например: 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "Удалить формат", "copy": "Копировать", "paste": "Вставить", "selectAll": "Выбрать все", "insertOrderedList": "Нумерованный список", "insertTable": "Вставить/изменить таблицу", "underline": "Подчеркивание", "foreColor": "Цвет текста", "htmlToggle": "Код HTML", "formatBlock": "Стиль абзаца", "insertHorizontalRule": "Горизонтальная линейка", "delete": "Удалить", "insertUnorderedList": "Список с маркерами", "tableProp": "Свойства таблицы", "insertImage": "Вставить изображение", "superscript": "Верхний индекс", "subscript": "Нижний индекс", "createLink": "Создать ссылку", "undo": "Отменить", "italic": "Курсив", "fontName": "Название шрифта", "justifyLeft": "По левому краю", "unlink": "Удалить ссылку", "toggleTableBorder": "Переключить рамку таблицы", "fontSize": "Размер шрифта", "indent": "Отступ", "redo": "Повторить", "strikethrough": "Перечеркивание", "justifyFull": "По ширине", "justifyCenter": "По центру", "hiliteColor": "Цвет фона", "deleteTable": "Удалить таблицу", "outdent": "Втяжка", "cut": "Вырезать", "plainFormatBlock": "Стиль абзаца", "bold": "Полужирный", "systemShortcutFF": "Действие \"${0}\" доступно в Mozilla Firefox только через сочетание клавиш. Используйте ${1}.", "justifyRight": "По правому краю", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "設定", "text": "文字:", "title": "鏈結 URL", "url": "URL:", "urlInvalidMessage": "URL 無效。請輸入完整的 URL,例如 'http://www.dojotoolkit.org'"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "移除格式", "copy": "複製", "paste": "貼上", "selectAll": "全選", "insertOrderedList": "編號清單", "insertTable": "插入/編輯表格", "underline": "底線", "foreColor": "前景顏色", "htmlToggle": "HTML 原始檔", "formatBlock": "段落樣式", "insertHorizontalRule": "水平尺規", "delete": "刪除", "insertUnorderedList": "項目符號清單", "tableProp": "表格內容", "insertImage": "插入影像", "superscript": "上標", "subscript": "下標", "createLink": "建立鏈結", "undo": "復原", "italic": "斜體", "fontName": "字型名稱", "justifyLeft": "靠左對齊", "unlink": "移除鏈結", "toggleTableBorder": "切換表格邊框", "fontSize": "字型大小", "indent": "縮排", "redo": "重做", "strikethrough": "加刪除線", "justifyFull": "對齊", "justifyCenter": "置中對齊", "hiliteColor": "背景顏色", "deleteTable": "刪除表格", "outdent": "凸排", "cut": "剪下", "plainFormatBlock": "段落樣式", "bold": "粗體", "systemShortcutFF": "\"${0}\" 動作在 Mozilla Firefox 中,只能使用鍵盤快速鍵。使用 ${1}。", "justifyRight": "靠右對齊", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1 +0,0 @@
|
||||
({"set": "设定", "text": "文本:", "title": "链接 URL", "url": "URL:", "urlInvalidMessage": "URL 无效。请输入完整的 URL,如“http://www.dojotoolkit.org”"})
|
||||
@@ -1 +0,0 @@
|
||||
({"removeFormat": "除去格式", "copy": "复制", "paste": "粘贴", "selectAll": "全选", "insertOrderedList": "编号列表", "insertTable": "插入/编辑表", "underline": "下划线", "foreColor": "前景色", "htmlToggle": "HTML 源代码", "formatBlock": "段落样式", "insertHorizontalRule": "水平线", "delete": "删除", "insertUnorderedList": "符号列表", "tableProp": "表属性", "insertImage": "插入图像", "superscript": "上标", "subscript": "下标", "createLink": "创建链接", "undo": "撤销", "italic": "斜体", "fontName": "字体名称", "justifyLeft": "左对齐", "unlink": "除去链接", "toggleTableBorder": "切换表边框", "fontSize": "字体大小", "indent": "增加缩进", "redo": "重做", "strikethrough": "删除线", "justifyFull": "对齐", "justifyCenter": "居中", "hiliteColor": "背景色", "deleteTable": "删除表", "outdent": "减少缩进", "cut": "剪切", "plainFormatBlock": "段落样式", "bold": "粗体", "systemShortcutFF": "只能在 Mozilla Firefox 中通过键盘快捷方式执行“${0}”操作。请使用 ${1}。", "justifyRight": "右对齐", "appleKey": "⌘${0}", "ctrlKey": "ctrl+${0}"})
|
||||
@@ -1,147 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor.plugins.AlwaysShowToolbar"] = true;
|
||||
dojo.provide("dijit._editor.plugins.AlwaysShowToolbar");
|
||||
|
||||
dojo.declare("dijit._editor.plugins.AlwaysShowToolbar", null,
|
||||
{
|
||||
_handleScroll: true,
|
||||
setEditor: function(e){
|
||||
this.editor=e;
|
||||
// setTimeout(dojo.hitch(this,this.enable),10000);
|
||||
e.onLoadDeferred.addCallback(dojo.hitch(this,this.enable));
|
||||
// this.scrollInterval = setInterval(dojo.hitch(this, "globalOnScrollHandler"), 100);
|
||||
},
|
||||
enable: function(d){
|
||||
this._updateHeight();
|
||||
this._connects=[dojo.connect(window,'onscroll',this,"globalOnScrollHandler"),
|
||||
dojo.connect(this.editor,'onNormalizedDisplayChanged',this,"_updateHeight")];
|
||||
return d;
|
||||
},
|
||||
_updateHeight: function(){
|
||||
// summary:
|
||||
// Updates the height of the editor area to fit the contents.
|
||||
var e=this.editor;
|
||||
if(!e.isLoaded){ return; }
|
||||
if(e.height){ return; }
|
||||
|
||||
var height = dojo.marginBox(e.editNode).h;
|
||||
if(dojo.isOpera){
|
||||
height = e.editNode.scrollHeight;
|
||||
}
|
||||
// console.debug('height',height);
|
||||
// alert(this.editNode);
|
||||
|
||||
//height maybe zero in some cases even though the content is not empty,
|
||||
//we try the height of body instead
|
||||
if(!height){
|
||||
height = dojo.marginBox(e.document.body).h;
|
||||
}
|
||||
|
||||
if(height == 0){
|
||||
console.debug("Can not figure out the height of the editing area!");
|
||||
return; //prevent setting height to 0
|
||||
}
|
||||
if(height != this._lastHeight){
|
||||
this._lastHeight = height;
|
||||
// this.editorObject.style.height = this._lastHeight + "px";
|
||||
dojo.marginBox(e.iframe, { h: this._lastHeight });
|
||||
// this.iframe.height=this._lastHeight+10+'px';
|
||||
// this.iframe.style.height=this._lastHeight+'px';
|
||||
}
|
||||
},
|
||||
_lastHeight: 0,
|
||||
globalOnScrollHandler: function(){
|
||||
var isIE = dojo.isIE && dojo.isIE<7;
|
||||
if(!this._handleScroll){ return; }
|
||||
var tdn = this.editor.toolbar.domNode;
|
||||
var db = dojo.body;
|
||||
|
||||
if(!this._scrollSetUp){
|
||||
this._scrollSetUp = true;
|
||||
this._scrollThreshold = dojo._abs(tdn, true).y;
|
||||
// console.log("threshold:", this._scrollThreshold);
|
||||
//what's this for?? comment out for now
|
||||
// if((isIE)&&(db)&&(dojo.style(db, "backgroundIimage")=="none")){
|
||||
// db.style.backgroundImage = "url(" + dojo.uri.moduleUri("dijit", "templates/blank.gif") + ")";
|
||||
// db.style.backgroundAttachment = "fixed";
|
||||
// }
|
||||
}
|
||||
|
||||
var scrollPos = dojo._docScroll().y;
|
||||
|
||||
if(scrollPos > this._scrollThreshold && scrollPos < this._scrollThreshold+this._lastHeight){
|
||||
// dojo.debug(scrollPos);
|
||||
if(!this._fixEnabled){
|
||||
var tdnbox = dojo.marginBox(tdn);
|
||||
this.editor.iframe.style.marginTop = tdnbox.h+"px";
|
||||
|
||||
if(isIE){
|
||||
tdn.style.left = dojo._abs(tdn).x;
|
||||
if(tdn.previousSibling){
|
||||
this._IEOriginalPos = ['after',tdn.previousSibling];
|
||||
}else if(tdn.nextSibling){
|
||||
this._IEOriginalPos = ['before',tdn.nextSibling];
|
||||
}else{
|
||||
this._IEOriginalPos = ['last',tdn.parentNode];
|
||||
}
|
||||
dojo.body().appendChild(tdn);
|
||||
dojo.addClass(tdn,'IEFixedToolbar');
|
||||
}else{
|
||||
with(tdn.style){
|
||||
position = "fixed";
|
||||
top = "0px";
|
||||
}
|
||||
}
|
||||
|
||||
dojo.marginBox(tdn, { w: tdnbox.w });
|
||||
tdn.style.zIndex = 2000;
|
||||
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.
|
||||
var eHeight = (this.height) ? parseInt(this.editor.height) : this.editor._lastHeight;
|
||||
if(scrollPos > (this._scrollThreshold+eHeight)){
|
||||
tdn.style.display = "none";
|
||||
}else{
|
||||
tdn.style.display = "";
|
||||
}
|
||||
}else if(this._fixEnabled){
|
||||
this.editor.iframe.style.marginTop = '';
|
||||
with(tdn.style){
|
||||
position = "";
|
||||
top = "";
|
||||
zIndex = "";
|
||||
display = "";
|
||||
}
|
||||
if(isIE){
|
||||
tdn.style.left = "";
|
||||
dojo.removeClass(tdn,'IEFixedToolbar');
|
||||
if(this._IEOriginalPos){
|
||||
dojo.place(tdn, this._IEOriginalPos[1], this._IEOriginalPos[0]);
|
||||
this._IEOriginalPos = null;
|
||||
}else{
|
||||
dojo.place(tdn, this.editor.iframe,'before');
|
||||
}
|
||||
}
|
||||
tdn.style.width = "";
|
||||
this._fixEnabled = false;
|
||||
}
|
||||
},
|
||||
destroy: function(){
|
||||
this._IEOriginalPos = null;
|
||||
this._handleScroll = false;
|
||||
dojo.forEach(this._connects,dojo.disconnect);
|
||||
// clearInterval(this.scrollInterval);
|
||||
|
||||
if(dojo.isIE && dojo.isIE<7){
|
||||
dojo.removeClass(this.editor.toolbar.domNode,'IEFixedToolbar');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,422 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor.plugins.EnterKeyHandling"] = true;
|
||||
dojo.provide("dijit._editor.plugins.EnterKeyHandling");
|
||||
|
||||
|
||||
dojo.declare("dijit._editor.plugins.EnterKeyHandling",null,{
|
||||
// blockNodeForEnter: String
|
||||
// this property decides the behavior of Enter key. It can be either P,
|
||||
// DIV, BR, or empty (which means disable this feature). Anything else
|
||||
// will trigger errors.
|
||||
blockNodeForEnter: 'P',
|
||||
constructor: function(args){
|
||||
if(args){
|
||||
dojo.mixin(this,args);
|
||||
}
|
||||
},
|
||||
setEditor: function(editor){
|
||||
this.editor=editor;
|
||||
if(this.blockNodeForEnter=='BR'){
|
||||
if(dojo.isIE){
|
||||
editor.contentDomPreFilters.push(dojo.hitch(this, "regularPsToSingleLinePs"));
|
||||
editor.contentDomPostFilters.push(dojo.hitch(this, "singleLinePsToRegularPs"));
|
||||
editor.onLoadDeferred.addCallback(dojo.hitch(this, "_fixNewLineBehaviorForIE"));
|
||||
}else{
|
||||
editor.onLoadDeferred.addCallback(dojo.hitch(this,function(d){
|
||||
try{
|
||||
this.editor.document.execCommand("insertBrOnReturn", false, true);
|
||||
}catch(e){};
|
||||
return d;
|
||||
}));
|
||||
}
|
||||
}else if(this.blockNodeForEnter){
|
||||
//add enter key handler
|
||||
// FIXME: need to port to the new event code!!
|
||||
dojo['require']('dijit._editor.range');
|
||||
var h=dojo.hitch(this,this.handleEnterKey);
|
||||
editor.addKeyHandler(13, 0, h); //enter
|
||||
editor.addKeyHandler(13, 2, h); //shift+enter
|
||||
this.connect(this.editor,'onKeyPressed','onKeyPressed');
|
||||
}
|
||||
},
|
||||
connect: function(o,f,tf){
|
||||
if(!this._connects){
|
||||
this._connects=[];
|
||||
}
|
||||
this._connects.push(dojo.connect(o,f,this,tf));
|
||||
},
|
||||
destroy: function(){
|
||||
dojo.forEach(this._connects,dojo.disconnect);
|
||||
this._connects=[];
|
||||
},
|
||||
onKeyPressed: function(e){
|
||||
if(this._checkListLater){
|
||||
if(dojo.withGlobal(this.editor.window, 'isCollapsed', dijit._editor.selection)){
|
||||
if(!dojo.withGlobal(this.editor.window, 'hasAncestorElement', dijit._editor.selection, ['LI'])){
|
||||
//circulate the undo detection code by calling RichText::execCommand directly
|
||||
dijit._editor.RichText.prototype.execCommand.apply(this.editor, ['formatblock',this.blockNodeForEnter]);
|
||||
//set the innerHTML of the new block node
|
||||
var block = dojo.withGlobal(this.editor.window, 'getAncestorElement', dijit._editor.selection, [this.blockNodeForEnter])
|
||||
if(block){
|
||||
block.innerHTML=this.bogusHtmlContent;
|
||||
if(dojo.isIE){
|
||||
//the following won't work, it will move the caret to the last list item in the previous list
|
||||
// var newrange = dijit.range.create();
|
||||
// newrange.setStart(block.firstChild,0);
|
||||
// var selection = dijit.range.getSelection(this.editor.window)
|
||||
// selection.removeAllRanges();
|
||||
// selection.addRange(newrange);
|
||||
//move to the start by move backward one char
|
||||
var r = this.editor.document.selection.createRange();
|
||||
r.move('character',-1);
|
||||
r.select();
|
||||
}
|
||||
}else{
|
||||
alert('onKeyPressed: Can not find the new block node');
|
||||
}
|
||||
}
|
||||
}
|
||||
this._checkListLater = false;
|
||||
}else if(this._pressedEnterInBlock){
|
||||
//the new created is the original current P, so we have previousSibling below
|
||||
this.removeTrailingBr(this._pressedEnterInBlock.previousSibling);
|
||||
delete this._pressedEnterInBlock;
|
||||
}
|
||||
},
|
||||
bogusHtmlContent: ' ',
|
||||
blockNodes: /^(?:H1|H2|H3|H4|H5|H6|LI)$/,
|
||||
handleEnterKey: function(e){
|
||||
// summary: manually handle enter key event to make the behavior consistant across
|
||||
// all supported browsers. See property blockNodeForEnter for available options
|
||||
if(!this.blockNodeForEnter){ return true; } //let browser handle this
|
||||
if(e.shiftKey //shift+enter always generates <br>
|
||||
|| this.blockNodeForEnter=='BR'){
|
||||
var parent = dojo.withGlobal(this.editor.window, "getParentElement", dijit._editor.selection);
|
||||
var header = dijit.range.getAncestor(parent,this.editor.blockNodes);
|
||||
if(header){
|
||||
if(header.tagName=='LI'){
|
||||
return true; //let brower handle
|
||||
}
|
||||
var selection = dijit.range.getSelection(this.editor.window);
|
||||
var range = selection.getRangeAt(0);
|
||||
if(!range.collapsed){
|
||||
range.deleteContents();
|
||||
}
|
||||
if(dijit.range.atBeginningOfContainer(header, range.startContainer, range.startOffset)){
|
||||
dojo.place(this.editor.document.createElement('br'), header, "before");
|
||||
}else if(dijit.range.atEndOfContainer(header, range.startContainer, range.startOffset)){
|
||||
dojo.place(this.editor.document.createElement('br'), header, "after");
|
||||
var newrange = dijit.range.create();
|
||||
newrange.setStartAfter(header);
|
||||
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(newrange);
|
||||
}else{
|
||||
return true; //let brower handle
|
||||
}
|
||||
}else{
|
||||
//don't change this: do not call this.execCommand, as that may have other logic in subclass
|
||||
// FIXME
|
||||
dijit._editor.RichText.prototype.execCommand.call(this.editor, 'inserthtml', '<br>');
|
||||
}
|
||||
return false;
|
||||
}
|
||||
var _letBrowserHandle = true;
|
||||
//blockNodeForEnter is either P or DIV
|
||||
//first remove selection
|
||||
var selection = dijit.range.getSelection(this.editor.window);
|
||||
var range = selection.getRangeAt(0);
|
||||
if(!range.collapsed){
|
||||
range.deleteContents();
|
||||
}
|
||||
|
||||
var block = dijit.range.getBlockAncestor(range.endContainer, null, this.editor.editNode);
|
||||
|
||||
if(block.blockNode && block.blockNode.tagName == 'LI'){
|
||||
this._checkListLater = true;
|
||||
return true;
|
||||
}else{
|
||||
this._checkListLater = false;
|
||||
}
|
||||
|
||||
//text node directly under body, let's wrap them in a node
|
||||
if(!block.blockNode){
|
||||
this.editor.document.execCommand('formatblock',false, this.blockNodeForEnter);
|
||||
//get the newly created block node
|
||||
// FIXME
|
||||
block = {blockNode:dojo.withGlobal(this.editor.window, "getAncestorElement", dijit._editor.selection, [this.blockNodeForEnter]),
|
||||
blockContainer: this.editor.editNode};
|
||||
if(block.blockNode){
|
||||
if((block.blockNode.textContent||block.blockNode.innerHTML).replace(/^\s+|\s+$/g, "").length==0){
|
||||
this.removeTrailingBr(block.blockNode);
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
block.blockNode = this.editor.editNode;
|
||||
}
|
||||
selection = dijit.range.getSelection(this.editor.window);
|
||||
range = selection.getRangeAt(0);
|
||||
}
|
||||
var newblock = this.editor.document.createElement(this.blockNodeForEnter);
|
||||
newblock.innerHTML=this.bogusHtmlContent;
|
||||
this.removeTrailingBr(block.blockNode);
|
||||
if(dijit.range.atEndOfContainer(block.blockNode, range.endContainer, range.endOffset)){
|
||||
if(block.blockNode === block.blockContainer){
|
||||
block.blockNode.appendChild(newblock);
|
||||
}else{
|
||||
dojo.place(newblock, block.blockNode, "after");
|
||||
}
|
||||
_letBrowserHandle = false;
|
||||
//lets move caret to the newly created block
|
||||
var newrange = dijit.range.create();
|
||||
newrange.setStart(newblock,0);
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(newrange);
|
||||
if(this.editor.height){
|
||||
newblock.scrollIntoView(false);
|
||||
}
|
||||
}else if(dijit.range.atBeginningOfContainer(block.blockNode,
|
||||
range.startContainer, range.startOffset)){
|
||||
if(block.blockNode === block.blockContainer){
|
||||
dojo.place(newblock, block.blockNode, "first");
|
||||
}else{
|
||||
dojo.place(newblock, block.blockNode, "before");
|
||||
}
|
||||
if(this.editor.height){
|
||||
//browser does not scroll the caret position into view, do it manually
|
||||
newblock.scrollIntoView(false);
|
||||
}
|
||||
_letBrowserHandle = false;
|
||||
}else{ //press enter in the middle of P
|
||||
if(dojo.isMoz){
|
||||
//press enter in middle of P may leave a trailing <br/>, let's remove it later
|
||||
this._pressedEnterInBlock = block.blockNode;
|
||||
}
|
||||
}
|
||||
return _letBrowserHandle;
|
||||
},
|
||||
removeTrailingBr: function(container){
|
||||
if(/P|DIV|LI/i .test(container.tagName)){
|
||||
var para = container;
|
||||
}else{
|
||||
var para = dijit._editor.selection.getParentOfType(container,['P','DIV','LI']);
|
||||
}
|
||||
|
||||
if(!para){ return; }
|
||||
if(para.lastChild){
|
||||
if(para.childNodes.length>1 && para.lastChild.nodeType==3 && /^[\s\xAD]*$/ .test(para.lastChild.nodeValue)){
|
||||
dojo._destroyElement(para.lastChild);
|
||||
}
|
||||
if(para.lastChild && para.lastChild.tagName=='BR'){
|
||||
dojo._destroyElement(para.lastChild);
|
||||
}
|
||||
}
|
||||
if(para.childNodes.length==0){
|
||||
para.innerHTML=this.bogusHtmlContent;
|
||||
}
|
||||
},
|
||||
_fixNewLineBehaviorForIE: function(d){
|
||||
if(typeof this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS == "undefined"){
|
||||
var lineFixingStyles = "p{margin:0 !important;}";
|
||||
var insertCssText = function(
|
||||
/*String*/ cssStr,
|
||||
/*Document*/ doc,
|
||||
/*String*/ URI)
|
||||
{
|
||||
// summary:
|
||||
// Attempt to insert CSS rules into the document through inserting a
|
||||
// style element
|
||||
|
||||
// DomNode Style = insertCssText(String ".dojoMenu {color: green;}"[, DomDoc document, dojo.uri.Uri Url ])
|
||||
if(!cssStr){
|
||||
return; // HTMLStyleElement
|
||||
}
|
||||
if(!doc){ doc = document; }
|
||||
// if(URI){// fix paths in cssStr
|
||||
// cssStr = dojo.html.fixPathsInCssText(cssStr, URI);
|
||||
// }
|
||||
var style = doc.createElement("style");
|
||||
style.setAttribute("type", "text/css");
|
||||
// IE is b0rken enough to require that we add the element to the doc
|
||||
// before changing it's properties
|
||||
var head = doc.getElementsByTagName("head")[0];
|
||||
if(!head){ // must have a head tag
|
||||
console.debug("No head tag in document, aborting styles");
|
||||
return; // HTMLStyleElement
|
||||
}else{
|
||||
head.appendChild(style);
|
||||
}
|
||||
if(style.styleSheet){// IE
|
||||
var setFunc = function(){
|
||||
try{
|
||||
style.styleSheet.cssText = cssStr;
|
||||
}catch(e){ dojo.debug(e); }
|
||||
};
|
||||
if(style.styleSheet.disabled){
|
||||
setTimeout(setFunc, 10);
|
||||
}else{
|
||||
setFunc();
|
||||
}
|
||||
}else{ // w3c
|
||||
var cssText = doc.createTextNode(cssStr);
|
||||
style.appendChild(cssText);
|
||||
}
|
||||
return style; // HTMLStyleElement
|
||||
}
|
||||
insertCssText(lineFixingStyles, this.editor.document);
|
||||
this.editor.document.__INSERTED_EDITIOR_NEWLINE_CSS = true;
|
||||
// this.regularPsToSingleLinePs(this.editNode);
|
||||
return d;
|
||||
}
|
||||
},
|
||||
regularPsToSingleLinePs: function(element, noWhiteSpaceInEmptyP){
|
||||
function wrapLinesInPs(el){
|
||||
// move "lines" of top-level text nodes into ps
|
||||
function wrapNodes(nodes){
|
||||
// nodes are assumed to all be siblings
|
||||
var newP = nodes[0].ownerDocument.createElement('p'); // FIXME: not very idiomatic
|
||||
nodes[0].parentNode.insertBefore(newP, nodes[0]);
|
||||
for(var i=0; i<nodes.length; i++){
|
||||
newP.appendChild(nodes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var currentNodeIndex = 0;
|
||||
var nodesInLine = [];
|
||||
var currentNode;
|
||||
while(currentNodeIndex < el.childNodes.length){
|
||||
currentNode = el.childNodes[currentNodeIndex];
|
||||
if( (currentNode.nodeName!='BR') &&
|
||||
(currentNode.nodeType==1) &&
|
||||
(dojo.style(currentNode, "display")!="block")
|
||||
){
|
||||
nodesInLine.push(currentNode);
|
||||
}else{
|
||||
// hit line delimiter; process nodesInLine if there are any
|
||||
var nextCurrentNode = currentNode.nextSibling;
|
||||
if(nodesInLine.length){
|
||||
wrapNodes(nodesInLine);
|
||||
currentNodeIndex = (currentNodeIndex+1)-nodesInLine.length;
|
||||
if(currentNode.nodeName=="BR"){
|
||||
dojo._destroyElement(currentNode);
|
||||
}
|
||||
}
|
||||
nodesInLine = [];
|
||||
}
|
||||
currentNodeIndex++;
|
||||
}
|
||||
if(nodesInLine.length){ wrapNodes(nodesInLine); }
|
||||
}
|
||||
|
||||
function splitP(el){
|
||||
// split a paragraph into seperate paragraphs at BRs
|
||||
var currentNode = null;
|
||||
var trailingNodes = [];
|
||||
var lastNodeIndex = el.childNodes.length-1;
|
||||
for(var i=lastNodeIndex; i>=0; i--){
|
||||
currentNode = el.childNodes[i];
|
||||
if(currentNode.nodeName=="BR"){
|
||||
var newP = currentNode.ownerDocument.createElement('p');
|
||||
dojo.place(newP, el, "after");
|
||||
if (trailingNodes.length==0 && i != lastNodeIndex) {
|
||||
newP.innerHTML = " "
|
||||
}
|
||||
dojo.forEach(trailingNodes, function(node){
|
||||
newP.appendChild(node);
|
||||
});
|
||||
dojo._destroyElement(currentNode);
|
||||
trailingNodes = [];
|
||||
}else{
|
||||
trailingNodes.unshift(currentNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var pList = [];
|
||||
var ps = element.getElementsByTagName('p');
|
||||
dojo.forEach(ps, function(p){ pList.push(p); });
|
||||
dojo.forEach(pList, function(p){
|
||||
if( (p.previousSibling) &&
|
||||
(p.previousSibling.nodeName == 'P' || dojo.style(p.previousSibling, 'display') != 'block')
|
||||
){
|
||||
var newP = p.parentNode.insertBefore(this.document.createElement('p'), p);
|
||||
// this is essential to prevent IE from losing the P.
|
||||
// if it's going to be innerHTML'd later we need
|
||||
// to add the to _really_ force the issue
|
||||
newP.innerHTML = noWhiteSpaceInEmptyP ? "" : " ";
|
||||
}
|
||||
splitP(p);
|
||||
},this.editor);
|
||||
wrapLinesInPs(element);
|
||||
return element;
|
||||
},
|
||||
|
||||
singleLinePsToRegularPs: function(element){
|
||||
function getParagraphParents(node){
|
||||
var ps = node.getElementsByTagName('p');
|
||||
var parents = [];
|
||||
for(var i=0; i<ps.length; i++){
|
||||
var p = ps[i];
|
||||
var knownParent = false;
|
||||
for(var k=0; k < parents.length; k++){
|
||||
if(parents[k] === p.parentNode){
|
||||
knownParent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!knownParent){
|
||||
parents.push(p.parentNode);
|
||||
}
|
||||
}
|
||||
return parents;
|
||||
}
|
||||
|
||||
function isParagraphDelimiter(node){
|
||||
if(node.nodeType != 1 || node.tagName != 'P'){
|
||||
return (dojo.style(node, 'display') == 'block');
|
||||
}else{
|
||||
if(!node.childNodes.length || node.innerHTML==" "){ return true }
|
||||
//return node.innerHTML.match(/^(<br\ ?\/?>| |\ \;)$/i);
|
||||
}
|
||||
}
|
||||
|
||||
var paragraphContainers = getParagraphParents(element);
|
||||
for(var i=0; i<paragraphContainers.length; i++){
|
||||
var container = paragraphContainers[i];
|
||||
var firstPInBlock = null;
|
||||
var node = container.firstChild;
|
||||
var deleteNode = null;
|
||||
while(node){
|
||||
if(node.nodeType != "1" || node.tagName != 'P'){
|
||||
firstPInBlock = null;
|
||||
}else if (isParagraphDelimiter(node)){
|
||||
deleteNode = node;
|
||||
firstPInBlock = null;
|
||||
}else{
|
||||
if(firstPInBlock == null){
|
||||
firstPInBlock = node;
|
||||
}else{
|
||||
if( (!firstPInBlock.lastChild || firstPInBlock.lastChild.nodeName != 'BR') &&
|
||||
(node.firstChild) &&
|
||||
(node.firstChild.nodeName != 'BR')
|
||||
){
|
||||
firstPInBlock.appendChild(this.editor.document.createElement('br'));
|
||||
}
|
||||
while(node.firstChild){
|
||||
firstPInBlock.appendChild(node.firstChild);
|
||||
}
|
||||
deleteNode = node;
|
||||
}
|
||||
}
|
||||
node = node.nextSibling;
|
||||
if(deleteNode){
|
||||
dojo._destroyElement(deleteNode);
|
||||
deleteNode = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor.plugins.FontChoice"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor.plugins.FontChoice"] = true;
|
||||
dojo.provide("dijit._editor.plugins.FontChoice");
|
||||
|
||||
dojo.require("dijit._editor._Plugin");
|
||||
dojo.require("dijit.form.FilteringSelect");
|
||||
dojo.require("dojo.data.ItemFileReadStore");
|
||||
dojo.require("dojo.i18n");
|
||||
|
||||
dojo.requireLocalization("dijit._editor", "FontChoice", null, "ROOT");
|
||||
|
||||
dojo.declare("dijit._editor.plugins.FontChoice",
|
||||
dijit._editor._Plugin,
|
||||
{
|
||||
_uniqueId: 0,
|
||||
|
||||
buttonClass: dijit.form.FilteringSelect,
|
||||
|
||||
_initButton: function(){
|
||||
this.inherited("_initButton", arguments);
|
||||
|
||||
//TODO: do we need nls for font names? provide css font lists? or otherwise make this more configurable?
|
||||
var names = {
|
||||
fontName: ["serif", "sans-serif", "monospaced", "cursive", "fantasy"],
|
||||
fontSize: [1,2,3,4,5,6,7],
|
||||
formatBlock: ["p", "h1", "h2", "h3", "pre"] }[this.command];
|
||||
var strings = dojo.i18n.getLocalization("dijit._editor", "FontChoice");
|
||||
var items = dojo.map(names, function(x){ return { name: strings[x], value: x }; });
|
||||
items.push({name:"", value:""}); // FilteringSelect doesn't like unmatched blank strings
|
||||
this.button.store = new dojo.data.ItemFileReadStore(
|
||||
{ data: { identifier: "value",
|
||||
items: items }
|
||||
});
|
||||
this.button.setValue("");
|
||||
|
||||
dojo.connect(this.button, "onChange", this, function(choice){
|
||||
this.editor.execCommand(this.command, choice);
|
||||
});
|
||||
},
|
||||
|
||||
updateState: function(){
|
||||
this.inherited("updateState", arguments);
|
||||
var _e = this.editor;
|
||||
var _c = this.command;
|
||||
if(!_e || !_e.isLoaded || !_c.length){ return; }
|
||||
if(this.button){
|
||||
var value = _e.queryCommandValue(_c);
|
||||
this.button.setValue(value);
|
||||
}
|
||||
},
|
||||
|
||||
setToolbar: function(){
|
||||
this.inherited("setToolbar", arguments);
|
||||
|
||||
var forRef = this.button;
|
||||
if(!forRef.id){ forRef.id = "dijitEditorButton-"+this.command+(this._uniqueId++); } //TODO: is this necessary? FilteringSelects always seem to have an id?
|
||||
var label = dojo.doc.createElement("label");
|
||||
label.setAttribute("for", forRef.id);
|
||||
var strings = dojo.i18n.getLocalization("dijit._editor", "FontChoice");
|
||||
label.appendChild(dojo.doc.createTextNode(strings[this.command]));
|
||||
dojo.place(label, this.button.domNode, "before");
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor.plugins.LinkDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor.plugins.LinkDialog"] = true;
|
||||
dojo.provide("dijit._editor.plugins.LinkDialog");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
dojo.require("dijit._editor._Plugin");
|
||||
dojo.require("dijit.Dialog");
|
||||
dojo.require("dijit.form.Button");
|
||||
dojo.require("dijit.form.ValidationTextBox");
|
||||
dojo.require("dojo.i18n");
|
||||
dojo.require("dojo.string");
|
||||
dojo.requireLocalization("dijit._editor", "LinkDialog", null, "ko,zh,ja,zh-tw,ru,it,ROOT,hu,fr,pt,pl,es,de,cs");
|
||||
|
||||
dojo.declare("dijit._editor.plugins.DualStateDropDownButton",
|
||||
dijit.form.DropDownButton,
|
||||
{
|
||||
// summary: a DropDownButton but button can be displayed in two states (checked or unchecked)
|
||||
setChecked: dijit.form.ToggleButton.prototype.setChecked
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare("dijit._editor.plugins.UrlTextBox",
|
||||
dijit.form.ValidationTextBox,
|
||||
{
|
||||
// summary: the URL input box we use in our dialog
|
||||
|
||||
// regular expression for URLs, generated from dojo.regexp.url()
|
||||
regExp: "((https?|ftps?)\\://|)(([0-9a-zA-Z]([-0-9a-zA-Z]{0,61}[0-9a-zA-Z])?\\.)+(arpa|aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|xxx|jobs|mobi|post|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|er|eu|es|et|fi|fj|fk|fm|fo|fr|ga|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sk|sl|sm|sn|sr|st|su|sv|sy|sz|tc|td|tf|tg|th|tj|tk|tm|tn|to|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)|(((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])|(0[xX]0*[\\da-fA-F]?[\\da-fA-F]\\.){3}0[xX]0*[\\da-fA-F]?[\\da-fA-F]|(0+[0-3][0-7][0-7]\\.){3}0+[0-3][0-7][0-7]|(0|[1-9]\\d{0,8}|[1-3]\\d{9}|4[01]\\d{8}|42[0-8]\\d{7}|429[0-3]\\d{6}|4294[0-8]\\d{5}|42949[0-5]\\d{4}|429496[0-6]\\d{3}|4294967[01]\\d{2}|42949672[0-8]\\d|429496729[0-5])|0[xX]0*[\\da-fA-F]{1,8}|([\\da-fA-F]{1,4}\\:){7}[\\da-fA-F]{1,4}|([\\da-fA-F]{1,4}\\:){6}((\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.){3}(\\d|[1-9]\\d|1\\d\\d|2[0-4]\\d|25[0-5])))(\\:(0|[1-9]\\d*))?(/([^?#\\s/]+/)*)?([^?#\\s/]+(\\?[^?#\\s/]*)?(#[A-Za-z][\\w.:-]*)?)?",
|
||||
|
||||
required: true,
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.inherited("postMixInProperties", arguments);
|
||||
this.invalidMessage = dojo.i18n.getLocalization("dijit._editor", "LinkDialog", this.lang).urlInvalidMessage;
|
||||
},
|
||||
|
||||
getValue: function(){
|
||||
if(!/^(https?|ftps?)/.test(this.textbox.value)){
|
||||
this.textbox.value="http://"+this.textbox.value;
|
||||
}
|
||||
return this.textbox.value;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare("dijit._editor.plugins.LinkDialog",
|
||||
dijit._editor._Plugin,
|
||||
{
|
||||
buttonClass: dijit._editor.plugins.DualStateDropDownButton,
|
||||
useDefaultCommand: false,
|
||||
command: "createLink",
|
||||
linkDialogTemplate: [
|
||||
"<label for='urlInput'>${url} </label>",
|
||||
"<input dojoType=dijit._editor.plugins.UrlTextBox name='urlInput'><br>",
|
||||
"<label for='textInput'>${text} </label>",
|
||||
"<input dojoType=dijit.form.TextBox name='textInput'>",
|
||||
"<br>",
|
||||
"<button dojoType=dijit.form.Button type='submit'>${set}</button>"
|
||||
].join(""),
|
||||
|
||||
constructor: function(){
|
||||
var _this = this;
|
||||
var messages = dojo.i18n.getLocalization("dijit._editor", "LinkDialog", this.lang);
|
||||
this.dropDown = new dijit.TooltipDialog({
|
||||
title: messages.title,
|
||||
execute: dojo.hitch(this, "setValue"),
|
||||
onOpen: function(){
|
||||
_this._onOpenDialog();
|
||||
dijit.TooltipDialog.prototype.onOpen.apply(this, arguments);
|
||||
},
|
||||
onCancel: function(){
|
||||
setTimeout(dojo.hitch(_this, "_onCloseDialog"),0);
|
||||
},
|
||||
onClose: dojo.hitch(this, "_onCloseDialog")
|
||||
});
|
||||
this.dropDown.setContent(dojo.string.substitute(this.linkDialogTemplate, messages));
|
||||
this.dropDown.startup();
|
||||
},
|
||||
|
||||
setValue: function(args){
|
||||
// summary: callback from the dialog when user hits "set" button
|
||||
//TODO: prevent closing popup if the text is empty
|
||||
this._onCloseDialog();
|
||||
if(dojo.isIE){ //see #4151
|
||||
var a = dojo.withGlobal(this.editor.window, "getAncestorElement",dijit._editor.selection, ['a']);
|
||||
if(a){
|
||||
dojo.withGlobal(this.editor.window, "selectElement",dijit._editor.selection, [a]);
|
||||
}
|
||||
}
|
||||
var attstr='href="'+args.urlInput+'" _djrealurl="'+args.urlInput+'"';
|
||||
// console.log(args,this.editor,'<a '+attstr+'>'+args.textInput+'</a>');
|
||||
this.editor.execCommand('inserthtml', '<a '+attstr+'>'+args.textInput+'</a>');
|
||||
// this.editor.execCommand(this.command, args.urlInput);
|
||||
},
|
||||
|
||||
// _savedSelection: null,
|
||||
_onCloseDialog: function(){
|
||||
// FIXME: IE is really messed up here!!
|
||||
if(dojo.isIE){
|
||||
if(this._savedSelection){
|
||||
var b=this._savedSelection;
|
||||
this._savedSelection=null;
|
||||
this.editor.focus();
|
||||
var range = this.editor.document.selection.createRange();
|
||||
range.moveToBookmark(b);
|
||||
range.select();
|
||||
}
|
||||
}else{this.editor.focus();
|
||||
}
|
||||
},
|
||||
_onOpenDialog: function(){
|
||||
var a = dojo.withGlobal(this.editor.window, "getAncestorElement",dijit._editor.selection, ['a']);
|
||||
var url='',text='';
|
||||
if(a){
|
||||
url=a.getAttribute('_djrealurl');
|
||||
text=a.textContent||a.innerText;
|
||||
dojo.withGlobal(this.editor.window, "selectElement",dijit._editor.selection, [a,true]);
|
||||
}else{
|
||||
text=dojo.withGlobal(this.editor.window, dijit._editor.selection.getSelectedText);
|
||||
}
|
||||
// FIXME: IE is *really* b0rken
|
||||
if(dojo.isIE){
|
||||
var range = this.editor.document.selection.createRange();
|
||||
this._savedSelection = range.getBookmark();
|
||||
}
|
||||
this.dropDown.setValues({'urlInput':url,'textInput':text});
|
||||
//dijit.focus(this.urlInput);
|
||||
},
|
||||
|
||||
updateState: function(){
|
||||
// summary: change shading on button if we are over a link (or not)
|
||||
|
||||
var _e = this.editor;
|
||||
if(!_e){ return; }
|
||||
if(!_e.isLoaded){ return; }
|
||||
if(this.button){
|
||||
try{
|
||||
// display button differently if there is an existing link associated with the current selection
|
||||
var hasA = dojo.withGlobal(this.editor.window, "hasAncestorElement",dijit._editor.selection, ['a']);
|
||||
this.button.setChecked(hasA);
|
||||
}catch(e){
|
||||
console.debug(e); //FIXME: probably shouldn't squelch an exception here
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor.plugins.TextColor"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor.plugins.TextColor"] = true;
|
||||
dojo.provide("dijit._editor.plugins.TextColor");
|
||||
|
||||
dojo.require("dijit._editor._Plugin");
|
||||
dojo.require("dijit.ColorPalette");
|
||||
|
||||
dojo.declare("dijit._editor.plugins.TextColor",
|
||||
dijit._editor._Plugin,
|
||||
{
|
||||
buttonClass: dijit.form.DropDownButton,
|
||||
|
||||
//TODO: set initial focus/selection state?
|
||||
|
||||
constructor: function(){
|
||||
this.dropDown = new dijit.ColorPalette();
|
||||
dojo.connect(this.dropDown, "onChange", this, function(color){
|
||||
this.editor.execCommand(this.command, color);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,566 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor.range"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor.range"] = true;
|
||||
dojo.provide("dijit._editor.range");
|
||||
|
||||
dijit.range={};
|
||||
|
||||
dijit.range.getIndex=function(/*DomNode*/node, /*DomNode*/parent){
|
||||
// dojo.profile.start("dijit.range.getIndex");
|
||||
var ret=[], retR=[];
|
||||
var stop = parent;
|
||||
var onode = node;
|
||||
|
||||
while(node != stop){
|
||||
var i = 0;
|
||||
var pnode = node.parentNode, n;
|
||||
while(n=pnode.childNodes[i++]){
|
||||
if(n===node){
|
||||
--i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i>=pnode.childNodes.length){
|
||||
dojo.debug("Error finding index of a node in dijit.range.getIndex");
|
||||
}
|
||||
ret.unshift(i);
|
||||
retR.unshift(i-pnode.childNodes.length);
|
||||
node = pnode;
|
||||
}
|
||||
|
||||
//normalized() can not be called so often to prevent
|
||||
//invalidating selection/range, so we have to detect
|
||||
//here that any text nodes in a row
|
||||
if(ret.length>0 && onode.nodeType==3){
|
||||
var n = onode.previousSibling;
|
||||
while(n && n.nodeType==3){
|
||||
ret[ret.length-1]--;
|
||||
n = n.previousSibling;
|
||||
}
|
||||
n = onode.nextSibling;
|
||||
while(n && n.nodeType==3){
|
||||
retR[retR.length-1]++;
|
||||
n = n.nextSibling;
|
||||
}
|
||||
}
|
||||
// dojo.profile.end("dijit.range.getIndex");
|
||||
return {o: ret, r:retR};
|
||||
}
|
||||
|
||||
dijit.range.getNode = function(/*Array*/index, /*DomNode*/parent){
|
||||
if(!dojo.isArray(index) || index.length==0){
|
||||
return parent;
|
||||
}
|
||||
var node = parent;
|
||||
// if(!node)debugger
|
||||
dojo.every(index, function(i){
|
||||
if(i>=0&&i< node.childNodes.length){
|
||||
node = node.childNodes[i];
|
||||
}else{
|
||||
node = null;
|
||||
console.debug('Error: can not find node with index',index,'under parent node',parent );
|
||||
return false; //terminate dojo.every
|
||||
}
|
||||
return true; //carry on the every loop
|
||||
});
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
dijit.range.getCommonAncestor = function(n1,n2,root){
|
||||
var getAncestors = function(n,root){
|
||||
var as=[];
|
||||
while(n){
|
||||
as.unshift(n);
|
||||
if(n!=root && n.tagName!='BODY'){
|
||||
n = n.parentNode;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return as;
|
||||
};
|
||||
var n1as = getAncestors(n1,root);
|
||||
var n2as = getAncestors(n2,root);
|
||||
|
||||
var m = Math.min(n1as.length,n2as.length);
|
||||
var com = n1as[0]; //at least, one element should be in the array: the root (BODY by default)
|
||||
for(var i=1;i<m;i++){
|
||||
if(n1as[i]===n2as[i]){
|
||||
com = n1as[i]
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return com;
|
||||
}
|
||||
|
||||
dijit.range.getAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
|
||||
root = root || node.ownerDocument.body;
|
||||
while(node && node !== root){
|
||||
var name = node.nodeName.toUpperCase() ;
|
||||
if(regex.test(name)){
|
||||
return node;
|
||||
}
|
||||
|
||||
node = node.parentNode;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
dijit.range.BlockTagNames = /^(?:P|DIV|H1|H2|H3|H4|H5|H6|ADDRESS|PRE|OL|UL|LI|DT|DE)$/;
|
||||
dijit.range.getBlockAncestor = function(/*DomNode*/node, /*RegEx?*/regex, /*DomNode?*/root){
|
||||
root = root || node.ownerDocument.body;
|
||||
regex = regex || dijit.range.BlockTagNames;
|
||||
var block=null, blockContainer;
|
||||
while(node && node !== root){
|
||||
var name = node.nodeName.toUpperCase() ;
|
||||
if(!block && regex.test(name)){
|
||||
block = node;
|
||||
}
|
||||
if(!blockContainer && (/^(?:BODY|TD|TH|CAPTION)$/).test(name)){
|
||||
blockContainer = node;
|
||||
}
|
||||
|
||||
node = node.parentNode;
|
||||
}
|
||||
return {blockNode:block, blockContainer:blockContainer || node.ownerDocument.body};
|
||||
}
|
||||
|
||||
dijit.range.atBeginningOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
|
||||
var atBeginning = false;
|
||||
var offsetAtBeginning = (offset == 0);
|
||||
if(!offsetAtBeginning && node.nodeType==3){ //if this is a text node, check whether the left part is all space
|
||||
if(dojo.trim(node.nodeValue.substr(0,offset))==0){
|
||||
offsetAtBeginning = true;
|
||||
}
|
||||
}
|
||||
if(offsetAtBeginning){
|
||||
var cnode = node;
|
||||
atBeginning = true;
|
||||
while(cnode && cnode !== container){
|
||||
if(cnode.previousSibling){
|
||||
atBeginning = false;
|
||||
break;
|
||||
}
|
||||
cnode = cnode.parentNode;
|
||||
}
|
||||
}
|
||||
return atBeginning;
|
||||
}
|
||||
|
||||
dijit.range.atEndOfContainer = function(/*DomNode*/container, /*DomNode*/node, /*Int*/offset){
|
||||
var atEnd = false;
|
||||
var offsetAtEnd = (offset == (node.length || node.childNodes.length));
|
||||
if(!offsetAtEnd && node.nodeType==3){ //if this is a text node, check whether the right part is all space
|
||||
if(dojo.trim(node.nodeValue.substr(offset))==0){
|
||||
offsetAtEnd = true;
|
||||
}
|
||||
}
|
||||
if(offsetAtEnd){
|
||||
var cnode = node;
|
||||
atEnd = true;
|
||||
while(cnode && cnode !== container){
|
||||
if(cnode.nextSibling){
|
||||
atEnd = false;
|
||||
break;
|
||||
}
|
||||
cnode = cnode.parentNode;
|
||||
}
|
||||
}
|
||||
return atEnd;
|
||||
}
|
||||
|
||||
dijit.range.adjacentNoneTextNode=function(startnode, next){
|
||||
var node = startnode;
|
||||
var len = (0-startnode.length) || 0;
|
||||
var prop = next?'nextSibling':'previousSibling';
|
||||
while(node){
|
||||
if(node.nodeType!=3){
|
||||
break;
|
||||
}
|
||||
len += node.length
|
||||
node = node[prop];
|
||||
}
|
||||
return [node,len];
|
||||
}
|
||||
|
||||
dijit.range._w3c = Boolean(window['getSelection']);
|
||||
dijit.range.create = function(){
|
||||
if(dijit.range._w3c){
|
||||
return document.createRange();
|
||||
}else{//IE
|
||||
return new dijit.range.W3CRange;
|
||||
}
|
||||
}
|
||||
|
||||
dijit.range.getSelection = function(win, /*Boolean?*/ignoreUpdate){
|
||||
if(dijit.range._w3c){
|
||||
return win.getSelection();
|
||||
}else{//IE
|
||||
var id=win.__W3CRange;
|
||||
if(!id || !dijit.range.ie.cachedSelection[id]){
|
||||
var s = new dijit.range.ie.selection(win);
|
||||
//use win as the key in an object is not reliable, which
|
||||
//can leads to quite odd behaviors. thus we generate a
|
||||
//string and use it as a key in the cache
|
||||
id=(new Date).getTime();
|
||||
while(id in dijit.range.ie.cachedSelection){
|
||||
id=id+1;
|
||||
}
|
||||
id=String(id);
|
||||
dijit.range.ie.cachedSelection[id] = s;
|
||||
}else{
|
||||
var s = dijit.range.ie.cachedSelection[id];
|
||||
}
|
||||
if(!ignoreUpdate){
|
||||
s._getCurrentSelection();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
if(!dijit.range._w3c){
|
||||
dijit.range.ie={
|
||||
cachedSelection: {},
|
||||
selection: function(win){
|
||||
this._ranges = [];
|
||||
this.addRange = function(r, /*boolean*/internal){
|
||||
this._ranges.push(r);
|
||||
if(!internal){
|
||||
r._select();
|
||||
}
|
||||
this.rangeCount = this._ranges.length;
|
||||
};
|
||||
this.removeAllRanges = function(){
|
||||
//don't detach, the range may be used later
|
||||
// for(var i=0;i<this._ranges.length;i++){
|
||||
// this._ranges[i].detach();
|
||||
// }
|
||||
this._ranges = [];
|
||||
this.rangeCount = 0;
|
||||
};
|
||||
var _initCurrentRange = function(){
|
||||
var r = win.document.selection.createRange();
|
||||
var type=win.document.selection.type.toUpperCase();
|
||||
if(type == "CONTROL"){
|
||||
//TODO: multiple range selection(?)
|
||||
return new dijit.range.W3CRange(dijit.range.ie.decomposeControlRange(r));
|
||||
}else{
|
||||
return new dijit.range.W3CRange(dijit.range.ie.decomposeTextRange(r));
|
||||
}
|
||||
};
|
||||
this.getRangeAt = function(i){
|
||||
return this._ranges[i];
|
||||
};
|
||||
this._getCurrentSelection = function(){
|
||||
this.removeAllRanges();
|
||||
var r=_initCurrentRange();
|
||||
if(r){
|
||||
this.addRange(r, true);
|
||||
}
|
||||
};
|
||||
},
|
||||
decomposeControlRange: function(range){
|
||||
var firstnode = range.item(0), lastnode = range.item(range.length-1)
|
||||
var startContainer = firstnode.parentNode, endContainer = lastnode.parentNode;
|
||||
var startOffset = dijit.range.getIndex(firstnode, startContainer).o;
|
||||
var endOffset = dijit.range.getIndex(lastnode, endContainer).o+1;
|
||||
return [[startContainer, startOffset],[endContainer, endOffset]];
|
||||
},
|
||||
getEndPoint: function(range, end){
|
||||
var atmrange = range.duplicate();
|
||||
atmrange.collapse(!end);
|
||||
var cmpstr = 'EndTo' + (end?'End':'Start');
|
||||
var parentNode = atmrange.parentElement();
|
||||
|
||||
var startnode, startOffset, lastNode;
|
||||
if(parentNode.childNodes.length>0){
|
||||
dojo.every(parentNode.childNodes, function(node,i){
|
||||
var calOffset;
|
||||
if(node.nodeType != 3){
|
||||
atmrange.moveToElementText(node);
|
||||
|
||||
if(atmrange.compareEndPoints(cmpstr,range) > 0){
|
||||
startnode = node.previousSibling;
|
||||
if(lastNode && lastNode.nodeType == 3){
|
||||
//where share we put the start? in the text node or after?
|
||||
startnode = lastNode;
|
||||
calOffset = true;
|
||||
}else{
|
||||
startnode = parentNode;
|
||||
startOffset = i;
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
if(i==parentNode.childNodes.length-1){
|
||||
startnode = parentNode;
|
||||
startOffset = parentNode.childNodes.length;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(i==parentNode.childNodes.length-1){//at the end of this node
|
||||
startnode = node;
|
||||
calOffset = true;
|
||||
}
|
||||
}
|
||||
// try{
|
||||
if(calOffset && startnode){
|
||||
var prevnode = dijit.range.adjacentNoneTextNode(startnode)[0];
|
||||
if(prevnode){
|
||||
startnode = prevnode.nextSibling;
|
||||
}else{
|
||||
startnode = parentNode.firstChild; //firstChild must be a text node
|
||||
}
|
||||
var prevnodeobj = dijit.range.adjacentNoneTextNode(startnode);
|
||||
prevnode = prevnodeobj[0];
|
||||
var lenoffset = prevnodeobj[1];
|
||||
if(prevnode){
|
||||
atmrange.moveToElementText(prevnode);
|
||||
atmrange.collapse(false);
|
||||
}else{
|
||||
atmrange.moveToElementText(parentNode);
|
||||
}
|
||||
atmrange.setEndPoint(cmpstr, range);
|
||||
startOffset = atmrange.text.length-lenoffset;
|
||||
|
||||
return false;
|
||||
}
|
||||
// }catch(e){ debugger }
|
||||
lastNode = node;
|
||||
return true;
|
||||
});
|
||||
}else{
|
||||
startnode = parentNode;
|
||||
startOffset = 0;
|
||||
}
|
||||
|
||||
//if at the end of startnode and we are dealing with start container, then
|
||||
//move the startnode to nextSibling if it is a text node
|
||||
//TODO: do this for end container?
|
||||
if(!end && startnode.nodeType!=3 && startOffset == startnode.childNodes.length){
|
||||
if(startnode.nextSibling && startnode.nextSibling.nodeType==3){
|
||||
startnode = startnode.nextSibling;
|
||||
startOffset = 0;
|
||||
}
|
||||
}
|
||||
return [startnode, startOffset];
|
||||
},
|
||||
setEndPoint: function(range, container, offset){
|
||||
//text node
|
||||
var atmrange = range.duplicate();
|
||||
if(container.nodeType!=3){ //normal node
|
||||
atmrange.moveToElementText(container);
|
||||
atmrange.collapse(true);
|
||||
if(offset == container.childNodes.length){
|
||||
if(offset > 0){
|
||||
//a simple atmrange.collapse(false); won't work here:
|
||||
//although moveToElementText(node) is supposed to encompass the content of the node,
|
||||
//but when collapse to end, it is in fact after the ending tag of node (collapse to start
|
||||
//is after the begining tag of node as expected)
|
||||
var node = container.lastChild;
|
||||
var len = 0;
|
||||
while(node && node.nodeType == 3){
|
||||
len += node.length;
|
||||
container = node; //pass through
|
||||
node = node.previousSibling;
|
||||
}
|
||||
if(node){
|
||||
atmrange.moveToElementText(node);
|
||||
}
|
||||
atmrange.collapse(false);
|
||||
offset = len; //pass through
|
||||
}else{ //no childNodes
|
||||
atmrange.moveToElementText(container);
|
||||
atmrange.collapse(true);
|
||||
}
|
||||
}else{
|
||||
if(offset > 0){
|
||||
var node = container.childNodes[offset-1];
|
||||
if(node.nodeType==3){
|
||||
container = node;
|
||||
offset = node.length;
|
||||
//pass through
|
||||
}else{
|
||||
atmrange.moveToElementText(node);
|
||||
atmrange.collapse(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(container.nodeType==3){
|
||||
var prevnodeobj = dijit.range.adjacentNoneTextNode(container);
|
||||
var prevnode = prevnodeobj[0], len = prevnodeobj[1];
|
||||
if(prevnode){
|
||||
atmrange.moveToElementText(prevnode);
|
||||
atmrange.collapse(false);
|
||||
//if contentEditable is not inherit, the above collapse won't make the end point
|
||||
//in the correctly position: it always has a -1 offset, so compensate it
|
||||
if(prevnode.contentEditable!='inherit'){
|
||||
len++;
|
||||
}
|
||||
}else{
|
||||
atmrange.moveToElementText(container.parentNode);
|
||||
atmrange.collapse(true);
|
||||
}
|
||||
|
||||
offset += len;
|
||||
if(offset>0){
|
||||
if(atmrange.moveEnd('character',offset) != offset){
|
||||
alert('Error when moving!');
|
||||
}
|
||||
atmrange.collapse(false);
|
||||
}
|
||||
}
|
||||
|
||||
return atmrange;
|
||||
},
|
||||
decomposeTextRange: function(range){
|
||||
var tmpary = dijit.range.ie.getEndPoint(range);
|
||||
var startContainter = tmpary[0], startOffset = tmpary[1];
|
||||
var endContainter = tmpary[0], endOffset = tmpary[1];
|
||||
|
||||
if(range.htmlText.length){
|
||||
if(range.htmlText == range.text){ //in the same text node
|
||||
endOffset = startOffset+range.text.length;
|
||||
}else{
|
||||
tmpary = dijit.range.ie.getEndPoint(range,true);
|
||||
endContainter = tmpary[0], endOffset = tmpary[1];
|
||||
}
|
||||
}
|
||||
return [[startContainter, startOffset],[endContainter, endOffset], range.parentElement()];
|
||||
},
|
||||
setRange: function(range, startContainter,
|
||||
startOffset, endContainter, endOffset, check){
|
||||
var startrange = dijit.range.ie.setEndPoint(range, startContainter, startOffset);
|
||||
range.setEndPoint('StartToStart', startrange);
|
||||
if(!this.collapsed){
|
||||
var endrange = dijit.range.ie.setEndPoint(range, endContainter, endOffset);
|
||||
range.setEndPoint('EndToEnd', endrange);
|
||||
}
|
||||
|
||||
return range;
|
||||
}
|
||||
}
|
||||
|
||||
dojo.declare("dijit.range.W3CRange",null, {
|
||||
constructor: function(){
|
||||
if(arguments.length>0){
|
||||
this.setStart(arguments[0][0][0],arguments[0][0][1]);
|
||||
this.setEnd(arguments[0][1][0],arguments[0][1][1],arguments[0][2]);
|
||||
}else{
|
||||
this.commonAncestorContainer = null;
|
||||
this.startContainer = null;
|
||||
this.startOffset = 0;
|
||||
this.endContainer = null;
|
||||
this.endOffset = 0;
|
||||
this.collapsed = true;
|
||||
}
|
||||
},
|
||||
_simpleSetEndPoint: function(node, range, end){
|
||||
var r = (this._body||node.ownerDocument.body).createTextRange();
|
||||
if(node.nodeType!=1){
|
||||
r.moveToElementText(node.parentNode);
|
||||
}else{
|
||||
r.moveToElementText(node);
|
||||
}
|
||||
r.collapse(true);
|
||||
range.setEndPoint(end?'EndToEnd':'StartToStart',r);
|
||||
},
|
||||
_updateInternal: function(__internal_common){
|
||||
if(this.startContainer !== this.endContainer){
|
||||
if(!__internal_common){
|
||||
var r = (this._body||this.startContainer.ownerDocument.body).createTextRange();
|
||||
this._simpleSetEndPoint(this.startContainer,r);
|
||||
this._simpleSetEndPoint(this.endContainer,r,true);
|
||||
__internal_common = r.parentElement();
|
||||
}
|
||||
this.commonAncestorContainer = dijit.range.getCommonAncestor(this.startContainer, this.endContainer, __internal_common);
|
||||
}else{
|
||||
this.commonAncestorContainer = this.startContainer;
|
||||
}
|
||||
this.collapsed = (this.startContainer === this.endContainer) && (this.startOffset == this.endOffset);
|
||||
},
|
||||
setStart: function(node, offset, __internal_common){
|
||||
if(this.startContainer === node && this.startOffset == offset){
|
||||
return;
|
||||
}
|
||||
delete this._cachedBookmark;
|
||||
|
||||
this.startContainer = node;
|
||||
this.startOffset = offset;
|
||||
if(!this.endContainer){
|
||||
this.setEnd(node, offset, __internal_common);
|
||||
}else{
|
||||
this._updateInternal(__internal_common);
|
||||
}
|
||||
},
|
||||
setEnd: function(node, offset, __internal_common){
|
||||
if(this.endContainer === node && this.endOffset == offset){
|
||||
return;
|
||||
}
|
||||
delete this._cachedBookmark;
|
||||
|
||||
this.endContainer = node;
|
||||
this.endOffset = offset;
|
||||
if(!this.startContainer){
|
||||
this.setStart(node, offset, __internal_common);
|
||||
}else{
|
||||
this._updateInternal(__internal_common);
|
||||
}
|
||||
},
|
||||
setStartAfter: function(node, offset){
|
||||
this._setPoint('setStart', node, offset, 1);
|
||||
},
|
||||
setStartBefore: function(node, offset){
|
||||
this._setPoint('setStart', node, offset, 0);
|
||||
},
|
||||
setEndAfter: function(node, offset){
|
||||
this._setPoint('setEnd', node, offset, 1);
|
||||
},
|
||||
setEndBefore: function(node, offset){
|
||||
this._setPoint('setEnd', node, offset, 0);
|
||||
},
|
||||
_setPoint: function(what, node, offset, ext){
|
||||
var index = dijit.range.getIndex(node, node.parentNode).o;
|
||||
this[what](node.parentNode, index.pop()+ext);
|
||||
},
|
||||
_getIERange: function(){
|
||||
var r=(this._body||this.endContainer.ownerDocument.body).createTextRange();
|
||||
dijit.range.ie.setRange(r, this.startContainer, this.startOffset, this.endContainer, this.endOffset);
|
||||
return r;
|
||||
},
|
||||
getBookmark: function(body){
|
||||
this._getIERange();
|
||||
return this._cachedBookmark;
|
||||
},
|
||||
_select: function(){
|
||||
var r = this._getIERange();
|
||||
r.select();
|
||||
},
|
||||
deleteContents: function(){
|
||||
var r = this._getIERange();
|
||||
r.pasteHTML('');
|
||||
this.endContainer = this.startContainer;
|
||||
this.endOffset = this.startOffset;
|
||||
this.collapsed = true;
|
||||
},
|
||||
cloneRange: function(){
|
||||
var r = new dijit.range.W3CRange([[this.startContainer,this.startOffset],
|
||||
[this.endContainer,this.endOffset]]);
|
||||
r._body = this._body;
|
||||
return r;
|
||||
},
|
||||
detach: function(){
|
||||
this._body = null;
|
||||
this.commonAncestorContainer = null;
|
||||
this.startContainer = null;
|
||||
this.startOffset = 0;
|
||||
this.endContainer = null;
|
||||
this.endOffset = 0;
|
||||
this.collapsed = true;
|
||||
}
|
||||
});
|
||||
} //if(!dijit.range._w3c)
|
||||
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._editor.selection"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._editor.selection"] = true;
|
||||
dojo.provide("dijit._editor.selection");
|
||||
|
||||
// FIXME:
|
||||
// all of these methods branch internally for IE. This is probably
|
||||
// sub-optimal in terms of runtime performance. We should investigate the
|
||||
// size difference for differentiating at definition time.
|
||||
|
||||
dojo.mixin(dijit._editor.selection, {
|
||||
getType: function(){
|
||||
// summary: Get the selection type (like document.select.type in IE).
|
||||
if(dojo.doc["selection"]){ //IE
|
||||
return dojo.doc.selection.type.toLowerCase();
|
||||
}else{
|
||||
var stype = "text";
|
||||
|
||||
// Check if the actual selection is a CONTROL (IMG, TABLE, HR, etc...).
|
||||
var oSel;
|
||||
try{
|
||||
oSel = dojo.global.getSelection();
|
||||
}catch(e){ /*squelch*/ }
|
||||
|
||||
if(oSel && oSel.rangeCount==1){
|
||||
var oRange = oSel.getRangeAt(0);
|
||||
if( (oRange.startContainer == oRange.endContainer) &&
|
||||
((oRange.endOffset - oRange.startOffset) == 1) &&
|
||||
(oRange.startContainer.nodeType != 3 /* text node*/)
|
||||
){
|
||||
stype = "control";
|
||||
}
|
||||
}
|
||||
return stype;
|
||||
}
|
||||
},
|
||||
|
||||
getSelectedText: function(){
|
||||
// summary:
|
||||
// Return the text (no html tags) included in the current selection or null if no text is selected
|
||||
if(dojo.doc["selection"]){ //IE
|
||||
if(dijit._editor.selection.getType() == 'control'){
|
||||
return null;
|
||||
}
|
||||
return dojo.doc.selection.createRange().text;
|
||||
}else{
|
||||
var selection = dojo.global.getSelection();
|
||||
if(selection){
|
||||
return selection.toString();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getSelectedHtml: function(){
|
||||
// summary:
|
||||
// Return the html of the current selection or null if unavailable
|
||||
if(dojo.doc["selection"]){ //IE
|
||||
if(dijit._editor.selection.getType() == 'control'){
|
||||
return null;
|
||||
}
|
||||
return dojo.doc.selection.createRange().htmlText;
|
||||
}else{
|
||||
var selection = dojo.global.getSelection();
|
||||
if(selection && selection.rangeCount){
|
||||
var frag = selection.getRangeAt(0).cloneContents();
|
||||
var div = document.createElement("div");
|
||||
div.appendChild(frag);
|
||||
return div.innerHTML;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
getSelectedElement: function(){
|
||||
// summary:
|
||||
// Retrieves the selected element (if any), just in the case that
|
||||
// a single element (object like and image or a table) is
|
||||
// selected.
|
||||
if(this.getType() == "control"){
|
||||
if(dojo.doc["selection"]){ //IE
|
||||
var range = dojo.doc.selection.createRange();
|
||||
if(range && range.item){
|
||||
return dojo.doc.selection.createRange().item(0);
|
||||
}
|
||||
}else{
|
||||
var selection = dojo.global.getSelection();
|
||||
return selection.anchorNode.childNodes[ selection.anchorOffset ];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
getParentElement: function(){
|
||||
// summary:
|
||||
// Get the parent element of the current selection
|
||||
if(this.getType() == "control"){
|
||||
var p = this.getSelectedElement();
|
||||
if(p){ return p.parentNode; }
|
||||
}else{
|
||||
if(dojo.doc["selection"]){ //IE
|
||||
return dojo.doc.selection.createRange().parentElement();
|
||||
}else{
|
||||
var selection = dojo.global.getSelection();
|
||||
if(selection){
|
||||
var node = selection.anchorNode;
|
||||
|
||||
while(node && (node.nodeType != 1)){ // not an element
|
||||
node = node.parentNode;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
hasAncestorElement: function(/*String*/tagName /* ... */){
|
||||
// summary:
|
||||
// Check whether current selection has a parent element which is
|
||||
// of type tagName (or one of the other specified tagName)
|
||||
return (this.getAncestorElement.apply(this, arguments) != null);
|
||||
},
|
||||
|
||||
getAncestorElement: function(/*String*/tagName /* ... */){
|
||||
// summary:
|
||||
// Return the parent element of the current selection which is of
|
||||
// type tagName (or one of the other specified tagName)
|
||||
|
||||
var node = this.getSelectedElement() || this.getParentElement();
|
||||
return this.getParentOfType(node, arguments);
|
||||
},
|
||||
|
||||
isTag: function(/*DomNode*/node, /*Array*/tags){
|
||||
if(node && node.tagName){
|
||||
var _nlc = node.tagName.toLowerCase();
|
||||
for(var i=0; i<tags.length; i++){
|
||||
var _tlc = String(tags[i]).toLowerCase();
|
||||
if(_nlc == _tlc){
|
||||
return _tlc;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
getParentOfType: function(/*DomNode*/node, /*Array*/tags){
|
||||
while(node){
|
||||
if(this.isTag(node, tags).length){
|
||||
return node;
|
||||
}
|
||||
node = node.parentNode;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
remove: function(){
|
||||
// summary: delete current selection
|
||||
var _s = dojo.doc.selection;
|
||||
if(_s){ //IE
|
||||
if(_s.type.toLowerCase() != "none"){
|
||||
_s.clear();
|
||||
}
|
||||
return _s;
|
||||
}else{
|
||||
_s = dojo.global.getSelection();
|
||||
_s.deleteFromDocument();
|
||||
return _s;
|
||||
}
|
||||
},
|
||||
|
||||
selectElementChildren: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
|
||||
// summary:
|
||||
// clear previous selection and select the content of the node
|
||||
// (excluding the node itself)
|
||||
var _window = dojo.global;
|
||||
var _document = dojo.doc;
|
||||
element = dojo.byId(element);
|
||||
if(_document.selection && dojo.body().createTextRange){ // IE
|
||||
var range = element.ownerDocument.body.createTextRange();
|
||||
range.moveToElementText(element);
|
||||
if(!nochangefocus){
|
||||
range.select();
|
||||
}
|
||||
}else if(_window["getSelection"]){
|
||||
var selection = _window.getSelection();
|
||||
if(selection["setBaseAndExtent"]){ // Safari
|
||||
selection.setBaseAndExtent(element, 0, element, element.innerText.length - 1);
|
||||
}else if(selection["selectAllChildren"]){ // Mozilla
|
||||
selection.selectAllChildren(element);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
selectElement: function(/*DomNode*/element,/*Boolean?*/nochangefocus){
|
||||
// summary:
|
||||
// clear previous selection and select element (including all its children)
|
||||
var _document = dojo.doc;
|
||||
element = dojo.byId(element);
|
||||
if(_document.selection && dojo.body().createTextRange){ // IE
|
||||
try{
|
||||
var range = dojo.body().createControlRange();
|
||||
range.addElement(element);
|
||||
if(!nochangefocus){
|
||||
range.select();
|
||||
}
|
||||
}catch(e){
|
||||
this.selectElementChildren(element,nochangefocus);
|
||||
}
|
||||
}else if(dojo.global["getSelection"]){
|
||||
var selection = dojo.global.getSelection();
|
||||
// FIXME: does this work on Safari?
|
||||
if(selection["removeAllRanges"]){ // Mozilla
|
||||
var range = _document.createRange() ;
|
||||
range.selectNode(element) ;
|
||||
selection.removeAllRanges() ;
|
||||
selection.addRange(range) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,408 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._tree.Controller"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._tree.Controller"] = true;
|
||||
dojo.provide("dijit._tree.Controller");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit.Tree");
|
||||
|
||||
dojo.declare(
|
||||
"dijit._tree.Controller",
|
||||
[dijit._Widget],
|
||||
{
|
||||
// Summary: _tree.Controller performs all basic operations on Tree
|
||||
// Description:
|
||||
// Controller is the component to operate on model.
|
||||
// Tree/_tree.Node know how to modify themselves and show to user,
|
||||
// but operating on the tree often involves higher-level extensible logic,
|
||||
// like: database synchronization, node loading, reacting on clicks etc.
|
||||
// That's why it is handled by separate controller.
|
||||
// Controller processes expand/collapse and should be used if you
|
||||
// modify a tree.
|
||||
|
||||
// treeId: String
|
||||
// id of Tree widget that I'm controlling
|
||||
treeId: "",
|
||||
|
||||
postMixInProperties: function(){
|
||||
// setup to handle events from tree
|
||||
|
||||
// if the store supports Notification, subscribe to the notifcation events
|
||||
if (this.store._features['dojo.data.api.Notification']){
|
||||
dojo.connect(this.store, "onNew", this, "onNew");
|
||||
dojo.connect(this.store, "onDelete", this, "onDelete");
|
||||
dojo.connect(this.store, "onSet", this, "onSet");
|
||||
}
|
||||
|
||||
|
||||
// setup to handle events from tree
|
||||
dojo.subscribe(this.treeId, this, "_listener");
|
||||
},
|
||||
|
||||
_listener: function(/*Object*/ message){
|
||||
// summary: dispatcher to handle events from tree
|
||||
var event = message.event;
|
||||
var eventHandler = "on" + event.charAt(0).toUpperCase() + event.substr(1);
|
||||
if(this[eventHandler]){
|
||||
this[eventHandler](message);
|
||||
}
|
||||
},
|
||||
|
||||
onBeforeTreeDestroy: function(message){
|
||||
dojo.unsubscribe(message.tree.id);
|
||||
},
|
||||
|
||||
onExecute: function(/*Object*/ message){
|
||||
// summary: an execute event has occured
|
||||
|
||||
message.node.tree.focusNode(message.node);
|
||||
|
||||
// TODO: user guide: tell users to listen for execute events
|
||||
console.log("execute message for " + message.node + ": ", message);
|
||||
},
|
||||
|
||||
onNext: function(/*Object*/ message){
|
||||
// summary: down arrow pressed; get next visible node, set focus there
|
||||
var returnNode = this._navToNextNode(message.node);
|
||||
if(returnNode && returnNode.isTreeNode){
|
||||
returnNode.tree.focusNode(returnNode);
|
||||
return returnNode;
|
||||
}
|
||||
},
|
||||
|
||||
onNew: function(/*Object*/ item, parentInfo){
|
||||
//summary: new event from the store.
|
||||
|
||||
if (parentInfo){
|
||||
var parent = this._itemNodeMap[this.store.getIdentity(parentInfo.item)];
|
||||
}
|
||||
|
||||
var childParams = {item:item};
|
||||
if (parent){
|
||||
if (!parent.isFolder){
|
||||
parent.makeFolder();
|
||||
}
|
||||
if (parent.state=="LOADED" || parent.isExpanded){
|
||||
var childrenMap=parent.addChildren([childParams]);
|
||||
}
|
||||
} else {
|
||||
var childrenMap=this.tree.addChildren([childParams]);
|
||||
}
|
||||
|
||||
if (childrenMap){
|
||||
dojo.mixin(this._itemNodeMap, childrenMap);
|
||||
//this._itemNodeMap[this.store.getIdentity(item)]=child;
|
||||
}
|
||||
},
|
||||
|
||||
onDelete: function(/*Object*/ message){
|
||||
//summary: delete event from the store
|
||||
//since the object has just been deleted, we need to
|
||||
//use the name directly
|
||||
var identity = this.store.getIdentity(message);
|
||||
var node = this._itemNodeMap[identity];
|
||||
|
||||
if (node){
|
||||
parent = node.getParent();
|
||||
parent.deleteNode(node);
|
||||
this._itemNodeMap[identity]=null;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
onSet: function(/*Object*/ message){
|
||||
//summary: set data event on an item in the store
|
||||
var identity = this.store.getIdentity(message);
|
||||
var node = this._itemNodeMap[identity];
|
||||
node.setLabelNode(this.store.getLabel(message));
|
||||
},
|
||||
|
||||
_navToNextNode: function(node){
|
||||
// summary: get next visible node
|
||||
var returnNode;
|
||||
// if this is an expanded node, get the first child
|
||||
if(node.isFolder && node.isExpanded && node.hasChildren()){
|
||||
returnNode = node.getChildren()[0];
|
||||
}else{
|
||||
// find a parent node with a sibling
|
||||
while(node.isTreeNode){
|
||||
returnNode = node.getNextSibling();
|
||||
if(returnNode){
|
||||
break;
|
||||
}
|
||||
node = node.getParent();
|
||||
}
|
||||
}
|
||||
return returnNode;
|
||||
},
|
||||
|
||||
onPrevious: function(/*Object*/ message){
|
||||
// summary: up arrow pressed; move to previous visible node
|
||||
|
||||
var nodeWidget = message.node;
|
||||
var returnWidget = nodeWidget;
|
||||
|
||||
// if younger siblings
|
||||
var previousSibling = nodeWidget.getPreviousSibling();
|
||||
if(previousSibling){
|
||||
nodeWidget = previousSibling;
|
||||
// if the previous nodeWidget is expanded, dive in deep
|
||||
while(nodeWidget.isFolder && nodeWidget.isExpanded && nodeWidget.hasChildren()){
|
||||
returnWidget = nodeWidget;
|
||||
// move to the last child
|
||||
var children = nodeWidget.getChildren();
|
||||
nodeWidget = children[children.length-1];
|
||||
}
|
||||
}else{
|
||||
// if this is the first child, return the parent
|
||||
nodeWidget = nodeWidget.getParent();
|
||||
}
|
||||
|
||||
if(nodeWidget && nodeWidget.isTreeNode){
|
||||
returnWidget = nodeWidget;
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
onZoomIn: function(/*Object*/ message){
|
||||
// summary: right arrow pressed; go to child node
|
||||
var nodeWidget = message.node;
|
||||
var returnWidget = nodeWidget;
|
||||
|
||||
// if not expanded, expand, else move to 1st child
|
||||
if(nodeWidget.isFolder && !nodeWidget.isExpanded){
|
||||
this._expand(nodeWidget);
|
||||
}else if(nodeWidget.hasChildren()){
|
||||
nodeWidget = nodeWidget.getChildren()[0];
|
||||
}
|
||||
|
||||
if(nodeWidget && nodeWidget.isTreeNode){
|
||||
returnWidget = nodeWidget;
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
onZoomOut: function(/*Object*/ message){
|
||||
// summary: left arrow pressed; go to parent
|
||||
|
||||
var node = message.node;
|
||||
var returnWidget = node;
|
||||
|
||||
// if not collapsed, collapse, else move to parent
|
||||
if(node.isFolder && node.isExpanded){
|
||||
this._collapse(node);
|
||||
}else{
|
||||
node = node.getParent();
|
||||
}
|
||||
if(node && node.isTreeNode){
|
||||
returnWidget = node;
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
onFirst: function(/*Object*/ message){
|
||||
// summary: home pressed; get first visible node, set focus there
|
||||
var returnNode = this._navToFirstNode(message.tree);
|
||||
if(returnNode){
|
||||
returnNode.tree.focusNode(returnNode);
|
||||
return returnNode;
|
||||
}
|
||||
},
|
||||
|
||||
_navToFirstNode: function(/*Object*/ tree){
|
||||
// summary: get first visible node
|
||||
var returnNode;
|
||||
if(tree){
|
||||
returnNode = tree.getChildren()[0];
|
||||
if(returnNode && returnNode.isTreeNode){
|
||||
return returnNode;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onLast: function(/*Object*/ message){
|
||||
// summary: end pressed; go to last visible node
|
||||
|
||||
var returnWidget = message.node.tree;
|
||||
|
||||
var lastChild = returnWidget;
|
||||
while(lastChild.isExpanded){
|
||||
var c = lastChild.getChildren();
|
||||
lastChild = c[c.length - 1];
|
||||
if(lastChild.isTreeNode){
|
||||
returnWidget = lastChild;
|
||||
}
|
||||
}
|
||||
|
||||
if(returnWidget && returnWidget.isTreeNode){
|
||||
returnWidget.tree.focusNode(returnWidget);
|
||||
return returnWidget;
|
||||
}
|
||||
},
|
||||
|
||||
onToggleOpen: function(/*Object*/ message){
|
||||
// summary: user clicked the +/- icon; expand or collapse my children.
|
||||
var node = message.node;
|
||||
if(node.isExpanded){
|
||||
this._collapse(node);
|
||||
}else{
|
||||
this._expand(node);
|
||||
}
|
||||
},
|
||||
|
||||
onLetterKeyNav: function(message){
|
||||
// summary: letter key pressed; search for node starting with first char = key
|
||||
var node = startNode = message.node;
|
||||
var tree = message.tree;
|
||||
var key = message.key;
|
||||
do{
|
||||
node = this._navToNextNode(node);
|
||||
//check for last node, jump to first node if necessary
|
||||
if(!node){
|
||||
node = this._navToFirstNode(tree);
|
||||
}
|
||||
}while(node !== startNode && (node.label.charAt(0).toLowerCase() != key));
|
||||
if(node && node.isTreeNode){
|
||||
// no need to set focus if back where we started
|
||||
if(node !== startNode){
|
||||
node.tree.focusNode(node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
},
|
||||
|
||||
_expand: function(node){
|
||||
if(node.isFolder){
|
||||
node.expand(); // skip trees or non-folders
|
||||
var t = node.tree;
|
||||
if(t.lastFocused){ t.focusNode(t.lastFocused); } // restore focus
|
||||
}
|
||||
},
|
||||
|
||||
_collapse: function(node){
|
||||
if(node.isFolder){
|
||||
// are we collapsing a child that has the tab index?
|
||||
if(dojo.query("[tabindex=0]", node.domNode).length > 0){
|
||||
node.tree.focusNode(node);
|
||||
}
|
||||
node.collapse();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
dojo.declare(
|
||||
"dijit._tree.DataController",
|
||||
dijit._tree.Controller,
|
||||
{
|
||||
// summary
|
||||
// Controller for tree that hooks up to dojo.data
|
||||
|
||||
onAfterTreeCreate: function(message){
|
||||
// when a tree is created, we query against the store to get the top level nodes
|
||||
// in the tree
|
||||
var tree = this.tree = message.tree;
|
||||
this._itemNodeMap={};
|
||||
|
||||
var _this = this;
|
||||
function onComplete(/*dojo.data.Item[]*/ items){
|
||||
var childParams=dojo.map(items,
|
||||
function(item){
|
||||
return {
|
||||
item: item,
|
||||
isFolder: _this.store.hasAttribute(item, _this.childrenAttr)
|
||||
};
|
||||
});
|
||||
|
||||
_this._itemNodeMap = tree.setChildren(childParams);
|
||||
}
|
||||
|
||||
this.store.fetch({ query: this.query, onComplete: onComplete });
|
||||
},
|
||||
|
||||
_expand: function(/*_TreeNode*/ node){
|
||||
var store = this.store;
|
||||
var getValue = this.store.getValue;
|
||||
|
||||
switch(node.state){
|
||||
case "LOADING":
|
||||
// ignore clicks while we are in the process of loading data
|
||||
return;
|
||||
|
||||
case "UNCHECKED":
|
||||
// need to load all the children, and then expand
|
||||
var parentItem = node.item;
|
||||
var childItems = store.getValues(parentItem, this.childrenAttr);
|
||||
|
||||
// count how many items need to be loaded
|
||||
var _waitCount = 0;
|
||||
dojo.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
|
||||
|
||||
if(_waitCount == 0){
|
||||
// all items are already loaded. proceed..
|
||||
this._onLoadAllItems(node, childItems);
|
||||
}else{
|
||||
// still waiting for some or all of the items to load
|
||||
node.markProcessing();
|
||||
|
||||
var _this = this;
|
||||
function onItem(item){
|
||||
if(--_waitCount == 0){
|
||||
// all nodes have been loaded, send them to the tree
|
||||
node.unmarkProcessing();
|
||||
_this._onLoadAllItems(node, childItems);
|
||||
}
|
||||
}
|
||||
dojo.forEach(childItems, function(item){
|
||||
if(!store.isItemLoaded(item)){
|
||||
store.loadItem({item: item, onItem: onItem});
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// data is already loaded; just proceed
|
||||
dijit._tree.Controller.prototype._expand.apply(this, arguments);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_onLoadAllItems: function(/*_TreeNode*/ node, /*dojo.data.Item[]*/ items){
|
||||
// sumary: callback when all the children of a given node have been loaded
|
||||
// TODO: should this be used when the top level nodes are loaded too?
|
||||
var childParams=dojo.map(items, function(item){
|
||||
return {
|
||||
item: item,
|
||||
isFolder: this.store.hasAttribute(item, this.childrenAttr)
|
||||
};
|
||||
}, this);
|
||||
|
||||
dojo.mixin(this._itemNodeMap,node.setChildren(childParams));
|
||||
|
||||
dijit._tree.Controller.prototype._expand.apply(this, arguments);
|
||||
},
|
||||
|
||||
_collapse: function(/*_TreeNode*/ node){
|
||||
if(node.state == "LOADING"){
|
||||
// ignore clicks while we are in the process of loading data
|
||||
return;
|
||||
}
|
||||
dijit._tree.Controller.prototype._collapse.apply(this, arguments);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<div class="dijitTreeNode dijitTreeExpandLeaf dijitTreeChildrenNo" waiRole="presentation"
|
||||
><span dojoAttachPoint="expandoNode" class="dijitTreeExpando" waiRole="presentation"
|
||||
></span
|
||||
><span dojoAttachPoint="expandoNodeText" class="dijitExpandoText" waiRole="presentation"
|
||||
></span
|
||||
>
|
||||
<div dojoAttachPoint="contentNode" class="dijitTreeContent" waiRole="presentation">
|
||||
<div dojoAttachPoint="iconNode" class="dijitInline dijitTreeIcon" waiRole="presentation"></div>
|
||||
<span dojoAttachPoint="labelNode" class="dijitTreeLabel" wairole="treeitem" tabindex="-1"></span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,15 +0,0 @@
|
||||
<div class="dijitTreeContainer" style="" waiRole="tree"
|
||||
dojoAttachEvent="onclick:_onClick,onkeypress:_onKeyPress">
|
||||
<div class="dijitTreeNode dijitTreeIsRoot dijitTreeExpandLeaf dijitTreeChildrenNo" waiRole="presentation"
|
||||
dojoAttachPoint="rowNode"
|
||||
><span dojoAttachPoint="expandoNode" class="dijitTreeExpando" waiRole="presentation"
|
||||
></span
|
||||
><span dojoAttachPoint="expandoNodeText" class="dijitExpandoText" waiRole="presentation"
|
||||
></span
|
||||
>
|
||||
<div dojoAttachPoint="contentNode" class="dijitTreeContent" waiRole="presentation">
|
||||
<div dojoAttachPoint="iconNode" class="dijitInline dijitTreeIcon" waiRole="presentation"></div>
|
||||
<span dojoAttachPoint="labelNode" class="dijitTreeLabel" wairole="treeitem" tabindex="0"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,146 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._tree.dndContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._tree.dndContainer"] = true;
|
||||
dojo.provide("dijit._tree.dndContainer");
|
||||
dojo.require("dojo.dnd.common");
|
||||
dojo.require("dojo.dnd.Container");
|
||||
|
||||
dojo.declare("dijit._tree.dndContainer",
|
||||
null,
|
||||
{
|
||||
constructor: function(tree, params){
|
||||
// summary: a constructor of the Container
|
||||
// tree: Node: node or node's id to build the container on
|
||||
// params: Object: a dict of parameters, which gets mixed into the object
|
||||
this.tree = tree;
|
||||
this.node = tree.domNode;
|
||||
dojo.mixin(this, params);
|
||||
|
||||
// class-specific variables
|
||||
this.map = {};
|
||||
this.current = null;
|
||||
|
||||
// states
|
||||
this.ContainerState = "";
|
||||
dojo.addClass(this.node, "dojoDndContainer");
|
||||
|
||||
// mark up children
|
||||
if(!(params && params._skipStartup)){
|
||||
this.startup();
|
||||
}
|
||||
|
||||
// set up events
|
||||
this.events = [
|
||||
dojo.connect(this.node, "onmouseover", this, "onMouseOver"),
|
||||
dojo.connect(this.node, "onmouseout", this, "onMouseOut"),
|
||||
|
||||
// cancel text selection and text dragging
|
||||
dojo.connect(this.node, "ondragstart", dojo, "stopEvent"),
|
||||
dojo.connect(this.node, "onselectstart", dojo, "stopEvent")
|
||||
];
|
||||
},
|
||||
|
||||
|
||||
// abstract access to the map
|
||||
getItem: function(/*String*/ key){
|
||||
// summary: returns a data item by its key (id)
|
||||
//console.log("Container getItem()", arguments,this.map, this.map[key], this.selection[key]);
|
||||
return this.selection[key];
|
||||
//return this.map[key]; // Object
|
||||
},
|
||||
|
||||
// mouse events
|
||||
onMouseOver: function(e){
|
||||
// summary: event processor for onmouseover
|
||||
// e: Event: mouse event
|
||||
var n = e.relatedTarget;
|
||||
while(n){
|
||||
if(n == this.node){ break; }
|
||||
try{
|
||||
n = n.parentNode;
|
||||
}catch(x){
|
||||
n = null;
|
||||
}
|
||||
}
|
||||
if(!n){
|
||||
this._changeState("Container", "Over");
|
||||
this.onOverEvent();
|
||||
}
|
||||
n = this._getChildByEvent(e);
|
||||
if(this.current == n){ return; }
|
||||
if(this.current){ this._removeItemClass(this.current, "Over"); }
|
||||
if(n){ this._addItemClass(n, "Over"); }
|
||||
this.current = n;
|
||||
},
|
||||
|
||||
onMouseOut: function(e){
|
||||
// summary: event processor for onmouseout
|
||||
// e: Event: mouse event
|
||||
for(var n = e.relatedTarget; n;){
|
||||
if(n == this.node){ return; }
|
||||
try{
|
||||
n = n.parentNode;
|
||||
}catch(x){
|
||||
n = null;
|
||||
}
|
||||
}
|
||||
if(this.current){
|
||||
this._removeItemClass(this.current, "Over");
|
||||
this.current = null;
|
||||
}
|
||||
this._changeState("Container", "");
|
||||
this.onOutEvent();
|
||||
},
|
||||
|
||||
_changeState: function(type, newState){
|
||||
// summary: changes a named state to new state value
|
||||
// type: String: a name of the state to change
|
||||
// newState: String: new state
|
||||
var prefix = "dojoDnd" + type;
|
||||
var state = type.toLowerCase() + "State";
|
||||
//dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
|
||||
dojo.removeClass(this.node, prefix + this[state]);
|
||||
dojo.addClass(this.node, prefix + newState);
|
||||
this[state] = newState;
|
||||
},
|
||||
|
||||
_getChildByEvent: function(e){
|
||||
// summary: gets a child, which is under the mouse at the moment, or null
|
||||
// e: Event: a mouse event
|
||||
var node = e.target;
|
||||
|
||||
if (node && dojo.hasClass(node,"dijitTreeLabel")){
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
markupFactory: function(tree, params){
|
||||
params._skipStartup = true;
|
||||
return new dijit._tree.dndContainer(tree, params);
|
||||
},
|
||||
|
||||
_addItemClass: function(node, type){
|
||||
// summary: adds a class with prefix "dojoDndItem"
|
||||
// node: Node: a node
|
||||
// type: String: a variable suffix for a class name
|
||||
dojo.addClass(node, "dojoDndItem" + type);
|
||||
},
|
||||
|
||||
_removeItemClass: function(node, type){
|
||||
// summary: removes a class with prefix "dojoDndItem"
|
||||
// node: Node: a node
|
||||
// type: String: a variable suffix for a class name
|
||||
dojo.removeClass(node, "dojoDndItem" + type);
|
||||
},
|
||||
|
||||
onOverEvent: function(){
|
||||
// summary: this function is called once, when mouse is over our container
|
||||
console.log("onOverEvent parent");
|
||||
},
|
||||
|
||||
onOutEvent: function(){
|
||||
// summary: this function is called once, when mouse is out of our container
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._tree.dndSelector"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._tree.dndSelector"] = true;
|
||||
dojo.provide("dijit._tree.dndSelector");
|
||||
dojo.require("dojo.dnd.common");
|
||||
dojo.require("dijit._tree.dndContainer");
|
||||
|
||||
dojo.declare("dijit._tree.dndSelector",
|
||||
dijit._tree.dndContainer,
|
||||
{
|
||||
constructor: function(tree, params){
|
||||
this.selection={};
|
||||
this.anchor = null;
|
||||
this.simpleSelection=false;
|
||||
|
||||
this.events.push(
|
||||
dojo.connect(this.tree.domNode, "onmousedown", this,"onMouseDown"),
|
||||
dojo.connect(this.tree.domNode, "onmouseup", this,"onMouseUp")
|
||||
);
|
||||
},
|
||||
|
||||
// object attributes (for markup)
|
||||
singular: false, // is singular property
|
||||
|
||||
// methods
|
||||
getSelectedItems: function(){
|
||||
var selectedItems = []
|
||||
for (var i in this.selection){
|
||||
selectedItems.push(dijit.getEnclosingWidget(this.selection[i]).item);
|
||||
}
|
||||
return selectedItems;
|
||||
},
|
||||
|
||||
getSelectedNodes: function(){
|
||||
return this.selection;
|
||||
},
|
||||
|
||||
selectNone: function(){
|
||||
// summary: unselects all items
|
||||
return this._removeSelection()._removeAnchor(); // self
|
||||
},
|
||||
|
||||
insertItems: function(item, parent){
|
||||
// summary: inserts new data items (see Container's insertNodes method for details)
|
||||
|
||||
//we actually need to add things to the store here instead of adding noes to the tree directly
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
// summary: prepares the object to be garbage-collected
|
||||
dojo.dnd.Selector.superclass.destroy.call(this);
|
||||
this.selection = this.anchor = null;
|
||||
},
|
||||
|
||||
// mouse events
|
||||
onMouseDown: function(e){
|
||||
// summary: event processor for onmousedown
|
||||
// e: Event: mouse event
|
||||
if(!this.current){ return; }
|
||||
|
||||
var item = dijit.getEnclosingWidget(this.current).item
|
||||
var id = this.tree.store.getIdentity(item);
|
||||
|
||||
if (!this.current.id) {
|
||||
this.current.id=id;
|
||||
}
|
||||
|
||||
if (!this.current.type) {
|
||||
this.current.type="data";
|
||||
}
|
||||
|
||||
if(!this.singular && !dojo.dnd.getCopyKeyState(e) && !e.shiftKey && (this.current.id in this.selection)){
|
||||
this.simpleSelection = true;
|
||||
dojo.stopEvent(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.singular){
|
||||
if(this.anchor == this.current){
|
||||
if(dojo.dnd.getCopyKeyState(e)){
|
||||
this.selectNone();
|
||||
}
|
||||
}else{
|
||||
this.selectNone();
|
||||
this.anchor = this.current;
|
||||
this._addItemClass(this.anchor, "Anchor");
|
||||
|
||||
this.selection[this.current.id] = this.current;
|
||||
}
|
||||
}else{
|
||||
if(!this.singular && e.shiftKey){
|
||||
if (dojo.dnd.getCopyKeyState(e)){
|
||||
//TODO add range to selection
|
||||
}else{
|
||||
//TODO select new range from anchor
|
||||
}
|
||||
}else{
|
||||
if(dojo.dnd.getCopyKeyState(e)){
|
||||
if(this.anchor == this.current){
|
||||
delete this.selection[this.anchor.id];
|
||||
this._removeAnchor();
|
||||
}else{
|
||||
if(this.current.id in this.selection){
|
||||
this._removeItemClass(this.current, "Selected");
|
||||
delete this.selection[this.current.id];
|
||||
}else{
|
||||
if(this.anchor){
|
||||
this._removeItemClass(this.anchor, "Anchor");
|
||||
this._addItemClass(this.anchor, "Selected");
|
||||
}
|
||||
this.anchor = this.current;
|
||||
this._addItemClass(this.current, "Anchor");
|
||||
this.selection[this.current.id] = this.current;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
var item = dijit.getEnclosingWidget(this.current).item
|
||||
var id = this.tree.store.getIdentity(item);
|
||||
if(!(id in this.selection)){
|
||||
this.selectNone();
|
||||
this.anchor = this.current;
|
||||
this._addItemClass(this.current, "Anchor");
|
||||
this.selection[id] = this.current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dojo.stopEvent(e);
|
||||
},
|
||||
|
||||
onMouseMove: function() {
|
||||
|
||||
},
|
||||
|
||||
onOverEvent: function() {
|
||||
this.onmousemoveEvent = dojo.connect(this.node, "onmousemove", this, "onMouseMove");
|
||||
},
|
||||
|
||||
onMouseUp: function(e){
|
||||
// summary: event processor for onmouseup
|
||||
// e: Event: mouse event
|
||||
if(!this.simpleSelection){ return; }
|
||||
this.simpleSelection = false;
|
||||
this.selectNone();
|
||||
if(this.current){
|
||||
this.anchor = this.current;
|
||||
this._addItemClass(this.anchor, "Anchor");
|
||||
this.selection[this.current.id] = this.current;
|
||||
}
|
||||
},
|
||||
_removeSelection: function(){
|
||||
// summary: unselects all items
|
||||
var e = dojo.dnd._empty;
|
||||
for(var i in this.selection){
|
||||
if(i in e){ continue; }
|
||||
var node = dojo.byId(i);
|
||||
if(node){ this._removeItemClass(node, "Selected"); }
|
||||
}
|
||||
this.selection = {};
|
||||
return this; // self
|
||||
},
|
||||
_removeAnchor: function(){
|
||||
if(this.anchor){
|
||||
this._removeItemClass(this.anchor, "Anchor");
|
||||
this.anchor = null;
|
||||
}
|
||||
return this; // self
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,346 +0,0 @@
|
||||
if(!dojo._hasResource["dijit._tree.dndSource"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit._tree.dndSource"] = true;
|
||||
dojo.provide("dijit._tree.dndSource");
|
||||
|
||||
dojo.require("dijit._tree.dndSelector");
|
||||
dojo.require("dojo.dnd.Manager");
|
||||
|
||||
dojo.declare("dijit._tree.dndSource", dijit._tree.dndSelector, {
|
||||
// summary: a Source object, which can be used as a DnD source, or a DnD target
|
||||
|
||||
// object attributes (for markup)
|
||||
isSource: true,
|
||||
copyOnly: false,
|
||||
skipForm: false,
|
||||
accept: ["text"],
|
||||
|
||||
constructor: function(node, params){
|
||||
// summary: a constructor of the Source
|
||||
// node: Node: node or node's id to build the source on
|
||||
// params: Object: a dict of parameters, recognized parameters are:
|
||||
// isSource: Boolean: can be used as a DnD source, if true; assumed to be "true" if omitted
|
||||
// accept: Array: list of accepted types (text strings) for a target; assumed to be ["text"] if omitted
|
||||
// horizontal: Boolean: a horizontal container, if true, vertical otherwise or when omitted
|
||||
// copyOnly: Boolean: always copy items, if true, use a state of Ctrl key otherwise
|
||||
// skipForm: Boolean: don't start the drag operation, if clicked on form elements
|
||||
// the rest of parameters are passed to the selector
|
||||
if(!params){ params = {}; }
|
||||
dojo.mixin(this, params);
|
||||
this.isSource = typeof params.isSource == "undefined" ? true : params.isSource;
|
||||
var type = params.accept instanceof Array ? params.accept : ["text"];
|
||||
this.accept = null;
|
||||
if(type.length){
|
||||
this.accept = {};
|
||||
for(var i = 0; i < type.length; ++i){
|
||||
this.accept[type[i]] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// class-specific variables
|
||||
this.isDragging = false;
|
||||
this.mouseDown = false;
|
||||
this.targetAnchor = null;
|
||||
this.targetBox = null;
|
||||
this.before = true;
|
||||
|
||||
// states
|
||||
this.sourceState = "";
|
||||
if(this.isSource){
|
||||
dojo.addClass(this.node, "dojoDndSource");
|
||||
}
|
||||
this.targetState = "";
|
||||
if(this.accept){
|
||||
dojo.addClass(this.node, "dojoDndTarget");
|
||||
}
|
||||
if(this.horizontal){
|
||||
dojo.addClass(this.node, "dojoDndHorizontal");
|
||||
}
|
||||
// set up events
|
||||
this.topics = [
|
||||
dojo.subscribe("/dnd/source/over", this, "onDndSourceOver"),
|
||||
dojo.subscribe("/dnd/start", this, "onDndStart"),
|
||||
dojo.subscribe("/dnd/drop", this, "onDndDrop"),
|
||||
dojo.subscribe("/dnd/cancel", this, "onDndCancel")
|
||||
];
|
||||
},
|
||||
|
||||
startup: function(){
|
||||
},
|
||||
|
||||
// methods
|
||||
checkAcceptance: function(source, nodes){
|
||||
// summary: checks, if the target can accept nodes from this source
|
||||
// source: Object: the source which provides items
|
||||
// nodes: Array: the list of transferred items
|
||||
return true; // Boolean
|
||||
},
|
||||
copyState: function(keyPressed){
|
||||
// summary: Returns true, if we need to copy items, false to move.
|
||||
// It is separated to be overwritten dynamically, if needed.
|
||||
// keyPressed: Boolean: the "copy" was pressed
|
||||
return this.copyOnly || keyPressed; // Boolean
|
||||
},
|
||||
destroy: function(){
|
||||
// summary: prepares the object to be garbage-collected
|
||||
this.inherited("destroy",arguments);
|
||||
dojo.forEach(this.topics, dojo.unsubscribe);
|
||||
this.targetAnchor = null;
|
||||
},
|
||||
|
||||
// markup methods
|
||||
markupFactory: function(params, node){
|
||||
params._skipStartup = true;
|
||||
return new dijit._tree.dndSource(node, params);
|
||||
},
|
||||
|
||||
// mouse event processors
|
||||
onMouseMove: function(e){
|
||||
// summary: event processor for onmousemove
|
||||
// e: Event: mouse event
|
||||
if(this.isDragging && this.targetState == "Disabled"){ return; }
|
||||
this.inherited("onMouseMove", arguments);
|
||||
var m = dojo.dnd.manager();
|
||||
if(this.isDragging){
|
||||
// calculate before/after
|
||||
|
||||
if (this.allowBetween){ // not implemented yet for tree since it has no concept of order
|
||||
var before = false;
|
||||
if(this.current){
|
||||
if(!this.targetBox || this.targetAnchor != this.current){
|
||||
this.targetBox = {
|
||||
xy: dojo.coords(this.current, true),
|
||||
w: this.current.offsetWidth,
|
||||
h: this.current.offsetHeight
|
||||
};
|
||||
}
|
||||
if(this.horizontal){
|
||||
before = (e.pageX - this.targetBox.xy.x) < (this.targetBox.w / 2);
|
||||
}else{
|
||||
before = (e.pageY - this.targetBox.xy.y) < (this.targetBox.h / 2);
|
||||
}
|
||||
}
|
||||
if(this.current != this.targetAnchor || before != this.before){
|
||||
this._markTargetAnchor(before);
|
||||
m.canDrop(!this.current || m.source != this || !(this.current.id in this.selection));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(this.mouseDown && this.isSource){
|
||||
var n = this.getSelectedNodes();
|
||||
var nodes=[];
|
||||
for (var i in n){
|
||||
nodes.push(n[i]);
|
||||
}
|
||||
if(nodes.length){
|
||||
m.startDrag(this, nodes, this.copyState(dojo.dnd.getCopyKeyState(e)));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onMouseDown: function(e){
|
||||
// summary: event processor for onmousedown
|
||||
// e: Event: mouse event
|
||||
this.mouseDown = true;
|
||||
this.inherited("onMouseDown",arguments);
|
||||
},
|
||||
|
||||
onMouseUp: function(e){
|
||||
// summary: event processor for onmouseup
|
||||
// e: Event: mouse event
|
||||
if(this.mouseDown){
|
||||
this.mouseDown = false;
|
||||
this.inherited("onMouseUp",arguments);
|
||||
}
|
||||
},
|
||||
|
||||
onMouseOver: function(e){
|
||||
// summary: event processor for onmouseover
|
||||
// e: Event: mouse event
|
||||
var n = e.relatedTarget;
|
||||
while(n){
|
||||
if(n == this.node){ break; }
|
||||
try{
|
||||
n = n.parentNode;
|
||||
}catch(x){
|
||||
n = null;
|
||||
}
|
||||
}
|
||||
if(!n){
|
||||
this._changeState("Container", "Over");
|
||||
this.onOverEvent();
|
||||
}
|
||||
n = this._getChildByEvent(e);
|
||||
if(this.current == n){ return; }
|
||||
if(this.current){ this._removeItemClass(this.current, "Over"); }
|
||||
if(n){
|
||||
this._addItemClass(n, "Over");
|
||||
if (this.isDragging){
|
||||
var m = dojo.dnd.manager();
|
||||
if (this.checkItemAcceptance(n,m.source)){
|
||||
m.canDrop(this.targetState != "Disabled" && (!this.current || m.source != this || !(this.current.id in this.selection)));
|
||||
}else{
|
||||
m.canDrop(false);
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
if (this.isDragging ){
|
||||
var m = dojo.dnd.manager();
|
||||
if (m.source && this.checkAcceptance(m.source,m.source.getSelectedNodes())){
|
||||
m.canDrop(this.targetState != "Disabled" && (!this.current || m.source != this || !(this.current.id in this.selection)));
|
||||
}else{
|
||||
m.canDrop(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.current = n;
|
||||
},
|
||||
|
||||
checkItemAcceptance: function(node, source){
|
||||
// summary: stub funciton to be overridden if one wants to check for the ability to drop at the node/item level
|
||||
return true;
|
||||
},
|
||||
|
||||
// topic event processors
|
||||
onDndSourceOver: function(source){
|
||||
// summary: topic event processor for /dnd/source/over, called when detected a current source
|
||||
// source: Object: the source which has the mouse over it
|
||||
if(this != source){
|
||||
this.mouseDown = false;
|
||||
if(this.targetAnchor){
|
||||
this._unmarkTargetAnchor();
|
||||
}
|
||||
}else if(this.isDragging){
|
||||
var m = dojo.dnd.manager();
|
||||
m.canDrop(this.targetState != "Disabled" && (!this.current || m.source != this || !(this.current.id in this.selection)));
|
||||
}
|
||||
},
|
||||
onDndStart: function(source, nodes, copy){
|
||||
// summary: topic event processor for /dnd/start, called to initiate the DnD operation
|
||||
// source: Object: the source which provides items
|
||||
// nodes: Array: the list of transferred items
|
||||
// copy: Boolean: copy items, if true, move items otherwise
|
||||
|
||||
console.log("onDndStart");
|
||||
if(this.isSource){
|
||||
this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
|
||||
}
|
||||
var accepted = this.checkAcceptance(source, nodes);
|
||||
|
||||
this._changeState("Target", accepted ? "" : "Disabled");
|
||||
|
||||
if(accepted){
|
||||
dojo.dnd.manager().overSource(this);
|
||||
}
|
||||
|
||||
this.isDragging = true;
|
||||
console.log("isDragging=true now");
|
||||
},
|
||||
|
||||
itemCreator: function(nodes){
|
||||
var items = []
|
||||
|
||||
for(var i=0;i<nodes.length;i++){
|
||||
items.push({
|
||||
"name":nodes[i].textContent,
|
||||
"id": nodes[i].id
|
||||
});
|
||||
}
|
||||
|
||||
return items;
|
||||
},
|
||||
|
||||
onDndDrop: function(source, nodes, copy){
|
||||
// summary: topic event processor for /dnd/drop, called to finish the DnD operation
|
||||
// source: Object: the source which provides items
|
||||
// nodes: Array: the list of transferred items
|
||||
// copy: Boolean: copy items, if true, move items otherwise
|
||||
|
||||
if (this.containerState=="Over"){
|
||||
this.isDragging=false;
|
||||
var target= this.current;
|
||||
var items = this.itemCreator(nodes, target);
|
||||
if (!target || target==this.tree.domNode){
|
||||
for (var i=0; i<items.length;i++){
|
||||
this.tree.store.newItem(items[i],null);
|
||||
}
|
||||
}else {
|
||||
for (var i=0; i<items.length;i++){
|
||||
pInfo={parent:dijit.getEnclosingWidget(target).item, attribute:"children"};
|
||||
var newItem = this.tree.store.newItem(items[i],pInfo);
|
||||
console.log("newItem: ", newItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onDndCancel: function(){
|
||||
// summary: topic event processor for /dnd/cancel, called to cancel the DnD operation
|
||||
if(this.targetAnchor){
|
||||
this._unmarkTargetAnchor();
|
||||
this.targetAnchor = null;
|
||||
}
|
||||
this.before = true;
|
||||
this.isDragging = false;
|
||||
this.mouseDown = false;
|
||||
this._changeState("Source", "");
|
||||
this._changeState("Target", "");
|
||||
},
|
||||
|
||||
// utilities
|
||||
|
||||
onOverEvent: function(){
|
||||
// summary: this function is called once, when mouse is over our container
|
||||
this.inherited("onOverEvent",arguments);
|
||||
dojo.dnd.manager().overSource(this);
|
||||
},
|
||||
onOutEvent: function(){
|
||||
// summary: this function is called once, when mouse is out of our container
|
||||
this.inherited("onOutEvent",arguments);
|
||||
dojo.dnd.manager().outSource(this);
|
||||
},
|
||||
_markTargetAnchor: function(before){
|
||||
// summary: assigns a class to the current target anchor based on "before" status
|
||||
// before: Boolean: insert before, if true, after otherwise
|
||||
if(this.current == this.targetAnchor && this.before == before){ return; }
|
||||
if(this.targetAnchor){
|
||||
this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
|
||||
}
|
||||
this.targetAnchor = this.current;
|
||||
this.targetBox = null;
|
||||
this.before = before;
|
||||
if(this.targetAnchor){
|
||||
this._addItemClass(this.targetAnchor, this.before ? "Before" : "After");
|
||||
}
|
||||
},
|
||||
_unmarkTargetAnchor: function(){
|
||||
// summary: removes a class of the current target anchor based on "before" status
|
||||
if(!this.targetAnchor){ return; }
|
||||
this._removeItemClass(this.targetAnchor, this.before ? "Before" : "After");
|
||||
this.targetAnchor = null;
|
||||
this.targetBox = null;
|
||||
this.before = true;
|
||||
},
|
||||
_markDndStatus: function(copy){
|
||||
// summary: changes source's state based on "copy" status
|
||||
this._changeState("Source", copy ? "Copied" : "Moved");
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare("dijit._tree.dndTarget", dijit._tree.dndSource, {
|
||||
// summary: a Target object, which can be used as a DnD target
|
||||
|
||||
constructor: function(node, params){
|
||||
// summary: a constructor of the Target --- see the Source constructor for details
|
||||
this.isSource = false;
|
||||
dojo.removeClass(this.node, "dojoDndSource");
|
||||
},
|
||||
|
||||
// markup methods
|
||||
markupFactory: function(params, node){
|
||||
params._skipStartup = true;
|
||||
return new dijit._tree.dndTarget(node, params);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,127 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
|
||||
benchReceive.php - example way to handle incoming benchmark data,
|
||||
or how to use JSON php class to mangle data. No benchmark data
|
||||
is stored currently.
|
||||
|
||||
--
|
||||
-- Table structure for table `benchmarks`
|
||||
--
|
||||
|
||||
CREATE TABLE `benchmarks` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`useragent` varchar(242) NOT NULL default '',
|
||||
`dojover` varchar(96) NOT NULL default '',
|
||||
`testNum` int(11) NOT NULL default '0',
|
||||
`dijit` varchar(64) NOT NULL default '',
|
||||
`testCount` int(11) NOT NULL default '0',
|
||||
`testAverage` float NOT NULL default '0',
|
||||
`testMethod` varchar(10) NOT NULL default '',
|
||||
`testTime` bigint(20) NOT NULL default '0',
|
||||
`dataSet` varchar(64) NOT NULL default '',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `dijit` (`dijit`,`testAverage`),
|
||||
KEY `dataSet` (`dataSet`)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
--
|
||||
-- [end table struct] --
|
||||
|
||||
*/
|
||||
|
||||
if (is_array($_POST)) {
|
||||
|
||||
$username = '';
|
||||
$password = '';
|
||||
$dataBase = '';
|
||||
$table = '';
|
||||
|
||||
mysql_connect("localhost",$username,$password);
|
||||
mysql_select_db($dataBase);
|
||||
|
||||
require("../../dojo/tests/resources/JSON.php");
|
||||
$json = new Services_JSON();
|
||||
|
||||
// see "escape()" call in benchTest.html
|
||||
$string = $json->decode(urldecode($_POST['key']));
|
||||
// $string = $json->decode($_POST['key']);
|
||||
|
||||
print "<h1>Thank YOU!</h1>";
|
||||
print "
|
||||
<p>Your results have been added to our database. No
|
||||
personal information outside of what you see here
|
||||
has been stored.
|
||||
</p>
|
||||
|
||||
<p>You can <a href= \"javascript:history.back()\">go back</a>
|
||||
and run more tests, or even better, load up another browser
|
||||
and the submit your tests again!
|
||||
</p>
|
||||
|
||||
<p>again ... thanks for your time.</p>
|
||||
|
||||
";
|
||||
|
||||
print "<h3>Results Submitted:</h3>";
|
||||
print "<pre style=\"font:6pt Terminal,sans-serif; border:1px solid #cecece; background-color:#ededed; padding:20px; \">";
|
||||
|
||||
$ua = $string->clientNavigator;
|
||||
$dojov = $string->dojoVersion;
|
||||
|
||||
print "Client: ".$ua."\n";
|
||||
print "Dojo v".$dojov."\n";
|
||||
|
||||
if (is_array($string->dataSet)) {
|
||||
print "\nTest Results:";
|
||||
// should client serialize a key, or is this safer?
|
||||
$dataSet = md5(serialize($string));
|
||||
foreach ($string->dataSet as $test) {
|
||||
$data = array(
|
||||
'dataSet' => $dataSet,
|
||||
'useragent' => $ua,
|
||||
'dojover' => $dojov,
|
||||
'testNum' => $test->testNum,
|
||||
'testMethod' => $test->testMethod,
|
||||
'testTime' => $test->testTime,
|
||||
'testAverage' => $test->testAverage,
|
||||
'testCount' => $test->testCount,
|
||||
'dijit' => $test->dijit
|
||||
);
|
||||
print_r($data);
|
||||
add_rec($table,$data);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_array($string->errors)) {
|
||||
// not saving errors at this point
|
||||
print "\nErrors:";
|
||||
foreach ($string->errors as $error) {
|
||||
print_r($error);
|
||||
}
|
||||
}
|
||||
print "</pre>";
|
||||
}
|
||||
|
||||
function add_rec($table, $data) {
|
||||
|
||||
if (!is_array($data)) { return FALSE; }
|
||||
|
||||
$keys = array_keys($data);
|
||||
$values = array_values($data);
|
||||
$field=0;
|
||||
|
||||
for ($field;$field<sizeof($data);$field++) {
|
||||
if (!ereg("^[0-9].*$",$keys[$field])) {
|
||||
$sqlfields = $sqlfields.$keys[$field]."=\"".$values[$field]."\", ";
|
||||
}
|
||||
}
|
||||
$sqlfields = (substr($sqlfields,0,(strlen($sqlfields)-2)));
|
||||
|
||||
if ($query = mysql_query("insert into $table set $sqlfields")) {
|
||||
$id = mysql_insert_id();
|
||||
return ($id); } else { return FALSE; }
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,189 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Dojo interactive benchmark tool</title>
|
||||
<script type="text/javascript" src="../../dojo/dojo.js"></script>
|
||||
<script type="text/javascript">
|
||||
// FIXME:
|
||||
// the url below points to dojo.inpdx.net/benchResults.php
|
||||
// need to setup DB on dtk.org and change URL here to store
|
||||
// results elsewhere ... work db structure in accompanying
|
||||
// .php file
|
||||
// basic stats are located at http://dojo.inpdx.net/benchmarks.html
|
||||
|
||||
dojo.require("dojo.fx");
|
||||
// FIXME: this seems an excessive fix for IE6 issue ...
|
||||
dojo.require("dijit.dijit");
|
||||
// dojo.require("dijit.form.Button");
|
||||
dojo.require("dijit.dijit-all");
|
||||
dojo.require("dojo.parser");
|
||||
|
||||
|
||||
// setup global variables
|
||||
var masterResults = { clientNavigator: navigator.userAgent, dataSet: [], errors: [] }
|
||||
var isRunning = false;
|
||||
var theCount, theClass, runner = null;
|
||||
var testCount = 0;
|
||||
dojo.addOnLoad(function(){
|
||||
theCount = dojo.byId('countNode');
|
||||
theClass = dojo.byId('classNode');
|
||||
runner = dojo.byId('runner');
|
||||
masterResults.dojoVersion = dojo.version.toString();
|
||||
});
|
||||
|
||||
|
||||
function _toggleRunMsg(){
|
||||
var newMsg = (isRunning) ? " Run Test " : " Running ..."
|
||||
dojo.fx.chain([
|
||||
dojo.fadeOut({
|
||||
node:runner,
|
||||
duration:200,
|
||||
onEnd: function(){
|
||||
runner.innerHTML = newMsg;
|
||||
isRunning=!isRunning;
|
||||
}
|
||||
}),
|
||||
dojo.fadeIn({ node:runner, duration: 200 })
|
||||
]).play();
|
||||
}
|
||||
|
||||
function runTest(){
|
||||
if(isRunning){ return; }
|
||||
_toggleRunMsg();
|
||||
setTimeout("_runRealTest()",1000);
|
||||
}
|
||||
|
||||
function _runRealTest(){
|
||||
|
||||
var _error = false;
|
||||
var count = theCount.value;
|
||||
var aclass = theClass.value.toString();
|
||||
var theMethod = (dojo.byId('parse').checked) ? "parse" : "create";
|
||||
|
||||
var tmpNode = document.createElement('div');
|
||||
|
||||
switch(theMethod){
|
||||
case "parse" :
|
||||
var tmpString = [];
|
||||
for(var i=0; i<count; i++){
|
||||
tmpString.push('<div dojoType="', aclass, '"></div>');
|
||||
}
|
||||
tmpNode.innerHTML = tmpString.join("");
|
||||
var tmpTimer = new Date().getTime();
|
||||
dojo.parser.parse(tmpNode);
|
||||
var endTime = new Date().getTime() - tmpTimer;
|
||||
break;
|
||||
case "create" :
|
||||
var construction = dojo.getObject(aclass);
|
||||
var tmpTimer = new Date().getTime();
|
||||
for(var i=0; i<count; i++){
|
||||
var tmp = new construction({});
|
||||
tmpNode.appendChild(tmp.domNode);
|
||||
}
|
||||
var endTime = new Date().getTime() - tmpTimer;
|
||||
break;
|
||||
}
|
||||
|
||||
var average = (endTime / count);
|
||||
var msg = "It took: "+endTime+"ms to "+theMethod+" "+count+" "+aclass+" widgets"+
|
||||
"<br>(average: "+average+" ms/widget)<br><br>";
|
||||
|
||||
masterResults.dataSet.push({
|
||||
testNum: ++testCount,
|
||||
dijit: aclass,
|
||||
testCount: count,
|
||||
testAverage: average,
|
||||
testMethod: theMethod,
|
||||
testTime: endTime
|
||||
});
|
||||
|
||||
dojo.byId("results").innerHTML += msg;
|
||||
setTimeout("_toggleRunMsg()",250);
|
||||
|
||||
// Nodes have to be in the document for IE7 to GC them.
|
||||
// Do this after generating the widgets to dispel
|
||||
// notion that widget parents have to be in document
|
||||
// a-priori.
|
||||
dojo.byId("limbo").appendChild(tmpNode);
|
||||
}
|
||||
|
||||
function doDebug(){
|
||||
var key = escape(dojo.toJson(masterResults));
|
||||
dojo.byId('hiddenHolder').value = key;
|
||||
return true;
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
@import "../../dijit/themes/tundra/tundra.css";
|
||||
@import "../../dijit/themes/dijit.css";
|
||||
@import "../../dojo/resources/dojo.css";
|
||||
@import "../../dijit/tests/css/dijitTests.css";
|
||||
|
||||
#limbo {
|
||||
display: none;
|
||||
}
|
||||
#theContainer {
|
||||
float:left;
|
||||
display: block; padding:12px; padding-top:0;
|
||||
width:420px; margin-left:20px;
|
||||
background-color:#fff; -moz-border-radius:8pt 8pt;
|
||||
border:2px solid #ededed;
|
||||
}
|
||||
#leftControl { float:left; width:300px; }
|
||||
#testControl, #submitControl { border:2px solid #ededed; padding:12px; -moz-border-radius:8pt 8pt; background-color:#fff; }
|
||||
#results { overflow:auto; height:300px; border:1px solid #ccc; color:darkred; padding:8px; }
|
||||
#results li { list-style-type: none; }
|
||||
#results ul { margin:0; padding:0; }
|
||||
.runHolder, .submitButton {
|
||||
border:1px solid #ccc; padding:3px; -moz-border-radius:8pt 8pt; text-align:center;
|
||||
cursor:pointer; background-color:#ededed; display:block; width:125px;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class="tundra">
|
||||
<div id="limbo"></div>
|
||||
<h1 class="testTitle">Dojo Benchmark Tool</h1>
|
||||
|
||||
<div id="leftControl">
|
||||
<div id="testControl">
|
||||
|
||||
Class: <input type="text" name="dijit" id="classNode" value="dijit.form.Button"><br><br>
|
||||
Count: <input type="text" name="count" id="countNode" value="100" size="4" ><br><br>
|
||||
|
||||
Method: <label for="parse">
|
||||
<input type="radio" name="theMethod" value="parse" id="parse" checked="on"> Parse
|
||||
</label>
|
||||
<label for="create">
|
||||
<input type="radio" name="theMethod" value="create" id="create"> Create
|
||||
</label>
|
||||
|
||||
<br><br>
|
||||
<span onclick="runTest()" class="runHolder"><span id="runner"> Run Test </span></span>
|
||||
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<div id="submitControl">
|
||||
<p>
|
||||
* The results of these tests are important to us. Please feel free to submit your dataSet
|
||||
to Dojotoolkit.org. Your privacy will be respected.
|
||||
|
||||
</p>
|
||||
<div id="hiddenResults">
|
||||
<form id="resultForm" action="http://dojo.inpdx.net/benchResults.php"
|
||||
method="POST" onsubmit="doDebug()">
|
||||
<input type="hidden" id="hiddenHolder" value="" name="key">
|
||||
<input type="submit" value=" Submit Data " class="submitButton">
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="theContainer"><h3>Results:</h3><div id="results"></div></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,73 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>PROGRAMMATIC - Dojo Widget Creation Test</title>
|
||||
<script type="text/javascript" src="../../dojo/dojo.js"></script>
|
||||
<script type="text/javascript" src="../dijit.js"></script>
|
||||
<script type="text/javascript">
|
||||
var queryCount = location.search.match(/count=(\d*)/);
|
||||
var count = (queryCount ? parseInt(queryCount[1]) : 100);
|
||||
var queryClass = location.search.match(/class=([a-zA-z.]*)/);
|
||||
var className = (queryClass ? queryClass[1] : "form.Button");
|
||||
|
||||
dojo.require("dijit." + className);
|
||||
dojo.require("dojo.parser");
|
||||
logMessage = window.alert;
|
||||
</script>
|
||||
<style type="text/css">
|
||||
@import "../themes/tundra/tundra.css";
|
||||
/* group multiple buttons in a row */
|
||||
.box {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.box .dojoButton {
|
||||
width: 80px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.dojoButtonContents {
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
#buttonContainer {
|
||||
border: 1px solid black;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#results {
|
||||
color: darkred;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class=tundra>
|
||||
<script language='javascript'>
|
||||
document.write("<h2>Currently Creating "+count+" "+className+" instances</h2>");
|
||||
</script>
|
||||
Pass <code>?count=<i><b>100</b></i></code> in the query string to change the number of widgets.<br>
|
||||
Pass <code>?class=<i><b>form.Button</b></i></code> in the query string to change the widget class.
|
||||
<h3 id="results"></h3>
|
||||
|
||||
<div id="buttonContainer" class='box'></div>
|
||||
<br>
|
||||
<script type="text/javascript">
|
||||
// See if we can make a widget in script and attach it to the DOM ourselves.
|
||||
var constructor = dojo.getObject("dijit."+className);
|
||||
function makeEm(){
|
||||
var container = dojo.byId("buttonContainer");
|
||||
var t0 = new Date().getTime();
|
||||
for (var i = 1; i <= count; i++) {
|
||||
var it =
|
||||
new constructor(
|
||||
{label:"Button "+i, onclick:'logMessage("clicked simple")'}
|
||||
);
|
||||
container.appendChild(it.domNode);
|
||||
it.domNode.style.display = '';
|
||||
}
|
||||
var t1 = new Date().getTime();
|
||||
dojo.byId("results").innerHTML = "It took " + (t1 - t0) + " msec to create " + count + " "+className+" instances programmatically.";
|
||||
}
|
||||
dojo.addOnLoad(makeEm);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,75 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>PROGRAMMATIC - Dojo Button 100 Test</title>
|
||||
<script type="text/javascript" src="../../dojo/dojo.js" XdjConfig='isDebug: true, debugAtAllCosts: true'></script>
|
||||
<script type="text/javascript">
|
||||
dojo.require("dijit.form.Button");
|
||||
dojo.require("dojo.parser");
|
||||
logMessage = window.alert;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@import "../themes/tundra/tundra.css";
|
||||
|
||||
/* group multiple buttons in a row */
|
||||
.box {
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
.box .dojoButton {
|
||||
width:80px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.dojoButtonContents {
|
||||
font-size: 1.6em;
|
||||
}
|
||||
|
||||
#buttonContainer {
|
||||
border:1px solid black;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
#results {
|
||||
color:darkred;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body class=tundra>
|
||||
<h2>Creating dojot.form.buttons programmatically</h2>
|
||||
<h3 id="results"></h3>
|
||||
|
||||
<div id="buttonContainer" class='box'></div>
|
||||
|
||||
<br>
|
||||
Pass "?count=<i><b>n</b></i>" in the query string to change the number of buttons.
|
||||
|
||||
<script type="text/javascript">
|
||||
// See if we can make a widget in script and attach it to the DOM ourselves.
|
||||
|
||||
function makeEm() {
|
||||
var queryCount = location.search.match(/count=(\d*)/);
|
||||
var count = (queryCount ? parseInt(queryCount[1]) : 100);
|
||||
var container = dojo.byId("buttonContainer");
|
||||
var t0 = new Date().getTime();
|
||||
for (var i = 1; i <= count; i++) {
|
||||
var it =
|
||||
new dijit.form.Button(
|
||||
{label:"Button "+i, onclick:'logMessage("clicked simple")'}
|
||||
);
|
||||
container.appendChild(it.domNode);
|
||||
it.domNode.style.display = '';
|
||||
}
|
||||
var t1 = new Date().getTime();
|
||||
dojo.byId("results").innerHTML = "It took " + (t1 - t0) + " msec to create " + count + " Buttons programmatically.";
|
||||
}
|
||||
dojo.addOnLoad(makeEm);
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,66 +0,0 @@
|
||||
<html>
|
||||
<style>
|
||||
th { vertical-align:bottom; }
|
||||
td {
|
||||
padding:10px;
|
||||
text-align:right;
|
||||
}
|
||||
.computer { vertical-align:top; }
|
||||
</style>
|
||||
<body>
|
||||
<h3>Widget instantiation timing test results</h3>
|
||||
|
||||
<table>
|
||||
|
||||
<tr><th rowspan=2>Computer/OS</th><th rowspan=2>Browser</th><th colspan=3>Parsing</th><th colspan=3>Programmatic</th></tr>
|
||||
<tr> <th>100</th><th>500</th><th>1000</th><th>100</th><th>500</th><th>1000</th></tr>
|
||||
<tr><td class='computer' rowspan=3>MacBook Pro 2.16<br> OS 10.4 2GB RAM</td>
|
||||
<td>FF (2.0.0.3)</td>
|
||||
<td>303</td><td>1724</td><td>3505</td>
|
||||
<td>195</td><td>1006</td><td>2266</td>
|
||||
</tr>
|
||||
<tr><td>Safari (2.04)</td>
|
||||
<td>192</td><td>1460</td><td>4463</td>
|
||||
<td>142</td><td>895</td><td>2403</td>
|
||||
</tr>
|
||||
<tr><td>WebKit Nightly (21223)</td>
|
||||
<td>110</td><td>540</td><td>1096</td>
|
||||
<td>85</td><td>458</td><td>940</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<tr><td class='computer' rowspan=2>Dell Precision 2.13 PPro<br> XP SP 2 - 2GB RAM</td>
|
||||
<td>FF (2.0.0.3)</td>
|
||||
<td>282</td><td>1266</td><td>2484</td>
|
||||
<td>250</td><td>890</td><td>1766</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>IE7 (7.0.5730.11)</td>
|
||||
<td>303</td><td>2079</td><td>5172</td>
|
||||
<td>203</td><td>1140</td><td>2422</td>
|
||||
</tr>
|
||||
|
||||
<tr><td><!--browser--></td>
|
||||
<td><!--100 parse--></td><td><!--500 parse--></td><td><!--1000 parse--></td>
|
||||
<td><!--100 code--></td><td><!--500 code--></td><td><!--1000 code--></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<H3>If you want to play:</H3>
|
||||
<p></p>
|
||||
<ol>
|
||||
<li> Run the following tests:
|
||||
<ul>
|
||||
<li><a href='http://dojotoolkit.org/~owen/bench/dojo/dijit/bench/test_Button-parse.php?count=100'>http://dojotoolkit.org/~owen/bench/dojo/dijit/bench/test_Button-parse.php?count=100</a></li>
|
||||
<li><a href='http://dojotoolkit.org/~owen/bench/dojo/dijit/bench/test_Button-programmatic.html?count=100'>http://dojotoolkit.org/~owen/bench/dojo/dijit/bench/test_Button-programmatic.html?count=100</a></li>
|
||||
</ul>
|
||||
<br>
|
||||
Change the "count=" to 100, 500, 1000 for each.
|
||||
<br><br>
|
||||
Restart the browser between each test/count. Run each test 3 times and record the smallest number.
|
||||
</li>
|
||||
<li>Record your tests in the copy of this file in SVN: <code>dijit/bench/test_Button-results.html</code> and check it in. Reference ticket #2968.</li>
|
||||
</ol>
|
||||
</body>
|
||||
@@ -1,186 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>test of various synchronous page searching methods</title>
|
||||
<style type="text/css">
|
||||
@import "../../dojo/resources/dojo.css";
|
||||
@import "../themes/tundra/tundra.css";
|
||||
</style>
|
||||
<script type="text/javascript" src="../../dojo/dojo.js"
|
||||
djConfig="parseOnLoad: true, isDebug: true"></script>
|
||||
<script type="text/javascript">
|
||||
dojo.require("dojo.parser"); // scan page for widgets and instantiate them
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
/* dummy widget for benchmarking purposes */
|
||||
dojo.declare(
|
||||
"SimpleButton",
|
||||
[ dijit._Widget, dijit._Templated ],
|
||||
function(){ },
|
||||
{
|
||||
label: "",
|
||||
|
||||
templateString: "<button dojoAttachEvent='onclick:onClick'>${label}</button>",
|
||||
|
||||
onClick: function(){
|
||||
this.domNode.style.backgroundColor="green";
|
||||
},
|
||||
postCreate: function(){
|
||||
}
|
||||
}
|
||||
);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<h1 style="font-size: 40px; line-height: 50px;">This page contains a huge number of nodes, most of which are "chaff".</h1>
|
||||
<h3>Here's the relative timings for this page</h3>
|
||||
<div id="profileOutputTable"></div>
|
||||
<!--
|
||||
<h3>And some comparison data</h3>
|
||||
<table border=1>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>IE
|
||||
<th>Safari
|
||||
<th>Gecko (on PC)
|
||||
<th>Gecko (on intel mac)
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>4890
|
||||
<td>3242
|
||||
<td>3094
|
||||
<td>3782
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
-->
|
||||
|
||||
|
||||
<?
|
||||
$containerDepth = 30;
|
||||
$leadingChaff = 100;
|
||||
$trailingChaff = 100;
|
||||
$items = 100;
|
||||
?>
|
||||
<?
|
||||
function generateChaff($iters){
|
||||
for($i=0;$i<$iters;$i++){ ?>
|
||||
<pre class="highlighted"><code><span class="hl-reserved">var </span><span class="hl-identifier">dlg</span><span class="hl-default"> = </span><span class="hl-reserved">new </span><span class="hl-identifier">blah</span><span class="hl-default">.</span><span class="hl-identifier">ext</span><span class="hl-default">.</span><span class="hl-identifier">LayoutDialog</span><span class="hl-brackets">(</span><span class="hl-identifier">config</span><span class="hl-code">.</span><span class="hl-identifier">id</span><span class="hl-code"> || </span><span class="hl-identifier">blah</span><span class="hl-code">.</span><span class="hl-identifier">util</span><span class="hl-code">.</span><span class="hl-identifier">Dom</span><span class="hl-code">.</span><span class="hl-identifier">generateId</span><span class="hl-brackets">()</span><span class="hl-code">, </span><span class="hl-brackets">{
|
||||
</span><span title="autoCreate" class="hl-identifier">autoCreate</span><span class="hl-code"> : </span><span class="hl-reserved">true</span><span class="hl-code">,
|
||||
</span><span title="minWidth" class="hl-identifier">minWidth</span><span class="hl-code">:</span><span class="hl-number">400</span><span class="hl-code">,
|
||||
</span><span title="minHeight" class="hl-identifier">minHeight</span><span class="hl-code">:</span><span class="hl-number">300</span><span class="hl-code">,
|
||||
</span>
|
||||
<span title="syncHeightBeforeShow" class="hl-identifier">syncHeightBeforeShow</span><span class="hl-code">: </span><span class="hl-reserved">true</span><span class="hl-code">,
|
||||
</span><span title="shadow" class="hl-identifier">shadow</span><span class="hl-code">:</span><span class="hl-reserved">true</span><span class="hl-code">,
|
||||
</span><span title="fixedcenter" class="hl-identifier">fixedcenter</span><span class="hl-code">: </span><span class="hl-reserved">true</span><span class="hl-code">,
|
||||
</span><span title="center" class="hl-identifier">center</span><span class="hl-code">:</span><span class="hl-brackets">{</span><span class="hl-identifier">autoScroll</span><span class="hl-code">:</span><span class="hl-reserved">false</span><span class="hl-brackets">}</span><span class="hl-code">,
|
||||
</span><span title="east" class="hl-identifier">east</span><span class="hl-code">:</span><span class="hl-brackets">{</span><span class="hl-identifier">split</span><span class="hl-code">:</span><span class="hl-reserved">true</span><span class="hl-code">,</span><span class="hl-identifier">initialSize</span><span class="hl-code">:</span><span class="hl-number">150</span><span class="hl-code">,</span><span class="hl-identifier">minSize</span><span class="hl-code">:</span><span class="hl-number">150</span><span class="hl-code">,</span><span class="hl-identifier">maxSize</span><span class="hl-code">:</span><span class="hl-number">250</span><span class="hl-brackets">}
|
||||
})</span><span class="hl-default">;
|
||||
</span><span class="hl-identifier">dlg</span><span class="hl-default">.</span><span class="hl-identifier">setTitle</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">Choose an Image</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-default">;
|
||||
</span><span class="hl-identifier">dlg</span><span class="hl-default">.</span><span class="hl-identifier">getEl</span><span class="hl-brackets">()</span><span class="hl-default">.</span><span class="hl-identifier">addClass</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">ychooser-dlg</span><span class="hl-quotes">'</span><span class="hl-brackets">)</span><span class="hl-default">;</span></code></pre><br />
|
||||
<pre class="highlighted"><code><span class="hl-reserved">var </span><span class="hl-identifier">animated</span><span class="hl-default"> = </span><span class="hl-reserved">new </span><span class="hl-identifier">blah</span><span class="hl-default">.</span><span class="hl-identifier">ext</span><span class="hl-default">.</span><span class="hl-identifier">Resizable</span><span class="hl-brackets">(</span><span class="hl-quotes">'</span><span class="hl-string">animated</span><span class="hl-quotes">'</span><span class="hl-code">, </span><span class="hl-brackets">{
|
||||
</span><span title="east" class="hl-identifier">width</span><span class="hl-code">: </span><span class="hl-number">200</span><span class="hl-code">,
|
||||
</span><span title="east" class="hl-identifier">height</span><span class="hl-code">: </span><span class="hl-number">100</span><span class="hl-code">,
|
||||
</span><span title="east" class="hl-identifier">minWidth</span><span class="hl-code">:</span><span class="hl-number">100</span><span class="hl-code">,
|
||||
</span><span class="hl-identifier">minHeight</span><span class="hl-code">:</span><span class="hl-number">50</span><span class="hl-code">,
|
||||
</span><span class="hl-identifier">animate</span><span class="hl-code">:</span><span class="hl-reserved">true</span><span class="hl-code">,
|
||||
</span><span class="hl-identifier">easing</span><span class="hl-code">: </span><span class="hl-identifier">YAHOO</span><span class="hl-code">.</span><span class="hl-identifier">util</span><span class="hl-code">.</span><span class="hl-identifier">Easing</span><span class="hl-code">.</span><span class="hl-identifier">backIn</span><span class="hl-code">,
|
||||
</span><span class="hl-identifier">duration</span><span class="hl-code">:</span><span class="hl-number">.6
|
||||
</span><span class="hl-brackets">})</span><span class="hl-default">;</span></code></pre>
|
||||
<h4>The standard Lorem Ipsum passage, used since the 1500s</h4>
|
||||
<p>
|
||||
"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do
|
||||
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim
|
||||
ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
||||
aliquip ex ea commodo consequat. Duis aute irure dolor in
|
||||
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
|
||||
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
|
||||
culpa qui officia deserunt mollit anim id est laborum."
|
||||
</p>
|
||||
|
||||
<h4>Section 1.10.32 of "de Finibus Bonorum et Malorum", written by Cicero in 45 BC</h4>
|
||||
|
||||
<p>
|
||||
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem
|
||||
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa
|
||||
quae ab illo inventore veritatis et quasi architecto beatae vitae
|
||||
dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit
|
||||
aspernatur aut odit aut fugit, sed quia consequuntur magni dolores
|
||||
eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam
|
||||
est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci
|
||||
velit, sed quia non numquam eius modi tempora incidunt ut labore et
|
||||
dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,
|
||||
quis nostrum exercitationem ullam corporis suscipit laboriosam,
|
||||
nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure
|
||||
reprehenderit qui in ea voluptate velit esse quam nihil molestiae
|
||||
consequatur, vel illum qui dolorem eum fugiat quo voluptas nulla
|
||||
pariatur?"
|
||||
</p>
|
||||
|
||||
<h4>1914 translation by H. Rackham</h4>
|
||||
|
||||
<p>
|
||||
"But I must explain to you how all this mistaken idea of denouncing
|
||||
pleasure and praising pain was born and I will give you a complete
|
||||
account of the system, and expound the actual teachings of the
|
||||
great explorer of the truth, the master-builder of human happiness.
|
||||
No one rejects, dislikes, or avoids pleasure itself, because it is
|
||||
pleasure, but because those who do not know how to pursue pleasure
|
||||
rationally encounter consequences that are extremely painful. Nor
|
||||
again is there anyone who loves or pursues or desires to obtain
|
||||
pain of itself, because it is pain, but because occasionally
|
||||
circumstances occur in which toil and pain can procure him some
|
||||
great pleasure. To take a trivial example, which of us ever
|
||||
undertakes laborious physical exercise, except to obtain some
|
||||
advantage from it? But who has any right to find fault with a man
|
||||
who chooses to enjoy a pleasure that has no annoying consequences,
|
||||
or one who avoids a pain that produces no resultant pleasure?"
|
||||
</p>
|
||||
<? }
|
||||
} // end generateChaff
|
||||
$widgetName = "SimpleButton";
|
||||
?>
|
||||
<? generateChaff($leadingChaff); ?>
|
||||
<hr>
|
||||
<? for($i=0;$i<$containerDepth;$i++){ ?>
|
||||
<table border="1" cellpadding="0" cellspacing="0" width="100%">
|
||||
<!--
|
||||
<table>
|
||||
-->
|
||||
<tr>
|
||||
<td>
|
||||
<br>
|
||||
chaff!
|
||||
<br>
|
||||
<? } ?>
|
||||
<? for($i=0;$i<$items;$i++){ ?>
|
||||
<div dojoType="<?= $widgetName ?>" label="item2 <?= $i ?>">item2 <?= $i ?></div>
|
||||
<? } ?>
|
||||
<? for($i=0;$i<$containerDepth;$i++){ ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<? } ?>
|
||||
<? generateChaff($trailingChaff); ?>
|
||||
<? for($i=0;$i<$items;$i++){ ?>
|
||||
<div dojoType="<?= $widgetName ?>" label="item2 <?= $i ?>"><span>item <?= $i ?></span></div>
|
||||
<? } ?>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
oldTime = new Date();
|
||||
dojo.addOnLoad(function(){
|
||||
var time = new Date().getTime() - oldTime;
|
||||
var p = document.createElement("p");
|
||||
alert("Widgets loaded in " + time + "ms");
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,93 +0,0 @@
|
||||
Changes from Dojo 0.4 dojo.widgets to new dijit project
|
||||
=======================================================
|
||||
|
||||
The widgets and widget infrastructure have been separated into separate project,
|
||||
vastly streamlined and with a new directory structure. There are many other changes.
|
||||
|
||||
Markup
|
||||
------
|
||||
|
||||
dojoType="button" replaced by dojoType="dijit.Button" Must use fully qualified class name,
|
||||
and it's case-sensitive.
|
||||
|
||||
Need to manually dojo.require("dojo.parser") to get parsing
|
||||
|
||||
Widget namespaces and widget auto-loading are desupported.
|
||||
|
||||
onClick="foo" now overrides (ie, replaces) the default onClick() function rather than attaching to it,
|
||||
so widget designers should make empty onClick() functions (when appropriate).
|
||||
|
||||
Programmatic creation
|
||||
---------------------
|
||||
Create widgets via
|
||||
|
||||
new dijit.Button(params, srcNodeRef)
|
||||
|
||||
createWidget() call removed since multiple renderers are no longer supported (see next section).
|
||||
|
||||
At least for the dijit widgets, all widgets are guaranteed to work programmatically, which in
|
||||
effect means that all widgets must have templates, unless the default <div> works.
|
||||
|
||||
Renderers
|
||||
---------
|
||||
Removed support for multiple renderers (svg & vml & a11y) for a single widget.
|
||||
If a widget wants to render differently on different platforms, there must be
|
||||
branching code inside the widget, or it needs to call a library that branches
|
||||
based on the browser type (like dojo.gfx or dojo.charting).
|
||||
|
||||
|
||||
Templates
|
||||
---------
|
||||
"this." is no longer used within ${} substitution notation. See ticket #2905.
|
||||
dojoRoot,buildScriptBase,dojoModuleUrl are no longer supported, but
|
||||
any JavaScript properties on the widget's 'this' may be referenced with dotted notation.
|
||||
The attributes dojoOn* are desupported (including dojoOnBuild);
|
||||
also can't use id attribute to affect a dojoAttachPoint.
|
||||
|
||||
dojoAttachEvent is case sensitive, so capitalization matters. You will probably have
|
||||
to change
|
||||
|
||||
dojoAttachEvent="onClick"
|
||||
|
||||
to
|
||||
|
||||
dojoAttachEvent="onclick: onClick"
|
||||
|
||||
(given that the event name is lowercase, and assuming that the method name is camel case)
|
||||
|
||||
lists within dojoAttachPoint, dojoAttachEvent, waiRole, and waiState are now comma-separated
|
||||
(not separated by semi-colons)
|
||||
|
||||
Standard HTML attributes like 'id', 'name', 'lang', etc. are carried over programmatically
|
||||
by the _Widget constructor and do not need to be declared in the template (see _Widget.attributeMap)
|
||||
|
||||
Parent/Child relationships
|
||||
--------------------------
|
||||
By default widgets exist as islands, not knowing about their parent widget or children widgets.
|
||||
The exception is the destroy() function which will also delete all descendant widgets.
|
||||
Some widgets like Tree and SplitContainer will know about their children, but those widgets
|
||||
will use the special mixins in Container.js / Layout.js.
|
||||
|
||||
Widget.js base class
|
||||
--------------------
|
||||
|
||||
- Widget.js, Domwidget.js, HtmlWidget.js combined into dijit.base.Widget, with TemplatedWidget mixin
|
||||
for widgets with templates
|
||||
|
||||
- on widget creation, postMixInProperties(), buildRendering() and postCreate() is called.
|
||||
fillInTemplate() is no longer called. In addition, those functions call signatures have changed.
|
||||
No arguments are passed. To get the source dom Node, just reference this.srcDomNode.
|
||||
When postCreate() is called the widget children don't yet exist.
|
||||
|
||||
- The TemplatedWidget mixin defines buildRendering(). widgetsInTemplate not ported yet.
|
||||
|
||||
- onResized() removed
|
||||
|
||||
- the whole parent/child relationship thing is gone
|
||||
|
||||
- extraArgs[] is gone
|
||||
|
||||
- postCreate() called but child widgets don't exist yet
|
||||
|
||||
- templateCssPath ignored. User must manually include tundra.css file
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@@ -1,380 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.Button"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.Button"] = true;
|
||||
dojo.provide("dijit.form.Button");
|
||||
|
||||
dojo.require("dijit.form._FormWidget");
|
||||
dojo.require("dijit._Container");
|
||||
|
||||
dojo.declare("dijit.form.Button", dijit.form._FormWidget, {
|
||||
/*
|
||||
* usage
|
||||
* <button dojoType="button" onClick="...">Hello world</button>
|
||||
*
|
||||
* var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
|
||||
* dojo.body().appendChild(button1.domNode);
|
||||
*/
|
||||
// summary
|
||||
// Basically the same thing as a normal HTML button, but with special styling.
|
||||
|
||||
// label: String
|
||||
// text to display in button
|
||||
label: "",
|
||||
|
||||
// showLabel: Boolean
|
||||
// whether or not to display the text label in button
|
||||
showLabel: true,
|
||||
|
||||
// iconClass: String
|
||||
// class to apply to div in button to make it display an icon
|
||||
iconClass: "",
|
||||
|
||||
type: "button",
|
||||
baseClass: "dijitButton",
|
||||
templateString:"<div class=\"dijit dijitLeft dijitInline dijitButton\"\n\tdojoAttachEvent=\"onclick:_onButtonClick,onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\"\n\t><div class='dijitRight'\n\t\t><button class=\"dijitStretch dijitButtonNode dijitButtonContents\" dojoAttachPoint=\"focusNode,titleNode\"\n\t\t\ttype=\"${type}\" waiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t\t><span class=\"dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\" \n \t\t\t\t><span class=\"dijitToggleButtonIconChar\">✓</span \n\t\t\t></span\n\t\t\t><span class=\"dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\">${label}</span\n\t\t></button\n\t></div\n></div>\n",
|
||||
|
||||
// TODO: set button's title to this.containerNode.innerText
|
||||
|
||||
_onClick: function(/*Event*/ e){
|
||||
// summary: internal function to handle click actions
|
||||
if(this.disabled){ return false; }
|
||||
this._clicked(); // widget click actions
|
||||
return this.onClick(e); // user click actions
|
||||
},
|
||||
|
||||
_onButtonClick: function(/*Event*/ e){
|
||||
// summary: callback when the user mouse clicks the button portion
|
||||
dojo.stopEvent(e);
|
||||
var okToSubmit = this._onClick(e) !== false; // returning nothing is same as true
|
||||
|
||||
// for some reason type=submit buttons don't automatically submit the form; do it manually
|
||||
if(this.type=="submit" && okToSubmit){
|
||||
for(var node=this.domNode; node; node=node.parentNode){
|
||||
var widget=dijit.byNode(node);
|
||||
if(widget && widget._onSubmit){
|
||||
widget._onSubmit(e);
|
||||
break;
|
||||
}
|
||||
if(node.tagName.toLowerCase() == "form"){
|
||||
node.submit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
// summary:
|
||||
// get label and set as title on button icon if necessary
|
||||
if (this.showLabel == false){
|
||||
var labelText = "";
|
||||
this.label = this.containerNode.innerHTML;
|
||||
labelText = dojo.trim(this.containerNode.innerText || this.containerNode.textContent);
|
||||
// set title attrib on iconNode
|
||||
this.titleNode.title=labelText;
|
||||
dojo.addClass(this.containerNode,"dijitDisplayNone");
|
||||
}
|
||||
this.inherited(arguments);
|
||||
},
|
||||
|
||||
onClick: function(/*Event*/ e){
|
||||
// summary: user callback for when button is clicked
|
||||
// if type="submit", return value != false to perform submit
|
||||
return true;
|
||||
},
|
||||
|
||||
_clicked: function(/*Event*/ e){
|
||||
// summary: internal replaceable function for when the button is clicked
|
||||
},
|
||||
|
||||
setLabel: function(/*String*/ content){
|
||||
// summary: reset the label (text) of the button; takes an HTML string
|
||||
this.containerNode.innerHTML = this.label = content;
|
||||
if(dojo.isMozilla){ // Firefox has re-render issues with tables
|
||||
var oldDisplay = dojo.getComputedStyle(this.domNode).display;
|
||||
this.domNode.style.display="none";
|
||||
var _this = this;
|
||||
setTimeout(function(){_this.domNode.style.display=oldDisplay;},1);
|
||||
}
|
||||
if (this.showLabel == false){
|
||||
this.titleNode.title=dojo.trim(this.containerNode.innerText || this.containerNode.textContent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* usage
|
||||
* <button dojoType="DropDownButton" label="Hello world"><div dojotype=dijit.Menu>...</div></button>
|
||||
*
|
||||
* var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
|
||||
* dojo.body().appendChild(button1);
|
||||
*/
|
||||
dojo.declare("dijit.form.DropDownButton", [dijit.form.Button, dijit._Container], {
|
||||
// summary
|
||||
// push the button and a menu shows up
|
||||
|
||||
baseClass : "dijitDropDownButton",
|
||||
|
||||
templateString:"<div class=\"dijit dijitLeft dijitInline\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse,onclick:_onDropDownClick,onkeydown:_onDropDownKeydown,onblur:_onDropDownBlur,onkeypress:_onKey\"\n\t><div class='dijitRight'>\n\t<button class=\"dijitStretch dijitButtonNode dijitButtonContents\" type=\"${type}\"\n\t\tdojoAttachPoint=\"focusNode,titleNode\" waiRole=\"button\" waiState=\"haspopup-true,labelledby-${id}_label\"\n\t\t><div class=\"dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\"></div\n\t\t><span class=\"dijitButtonText\" \tdojoAttachPoint=\"containerNode,popupStateNode\"\n\t\tid=\"${id}_label\">${label}</span\n\t\t><span class='dijitA11yDownArrow'>▼</span>\n\t</button>\n</div></div>\n",
|
||||
|
||||
_fillContent: function(){
|
||||
// my inner HTML contains both the button contents and a drop down widget, like
|
||||
// <DropDownButton> <span>push me</span> <Menu> ... </Menu> </DropDownButton>
|
||||
// The first node is assumed to be the button content. The widget is the popup.
|
||||
if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
|
||||
//FIXME: figure out how to filter out the widget and use all remaining nodes as button
|
||||
// content, not just nodes[0]
|
||||
var nodes = dojo.query("*", this.srcNodeRef);
|
||||
dijit.form.DropDownButton.superclass._fillContent.call(this, nodes[0]);
|
||||
|
||||
// save pointer to srcNode so we can grab the drop down widget after it's instantiated
|
||||
this.dropDownContainer = this.srcNodeRef;
|
||||
}
|
||||
},
|
||||
|
||||
startup: function(){
|
||||
// the child widget from srcNodeRef is the dropdown widget. Insert it in the page DOM,
|
||||
// make it invisible, and store a reference to pass to the popup code.
|
||||
if(!this.dropDown){
|
||||
var dropDownNode = dojo.query("[widgetId]", this.dropDownContainer)[0];
|
||||
this.dropDown = dijit.byNode(dropDownNode);
|
||||
delete this.dropDownContainer;
|
||||
}
|
||||
dojo.body().appendChild(this.dropDown.domNode);
|
||||
this.dropDown.domNode.style.display="none";
|
||||
},
|
||||
|
||||
_onArrowClick: function(/*Event*/ e){
|
||||
// summary: callback when the user mouse clicks on menu popup node
|
||||
if(this.disabled){ return; }
|
||||
this._toggleDropDown();
|
||||
},
|
||||
|
||||
_onDropDownClick: function(/*Event*/ e){
|
||||
// on Firefox 2 on the Mac it is possible to fire onclick
|
||||
// by pressing enter down on a second element and transferring
|
||||
// focus to the DropDownButton;
|
||||
// we want to prevent opening our menu in this situation
|
||||
// and only do so if we have seen a keydown on this button;
|
||||
// e.detail != 0 means that we were fired by mouse
|
||||
var isMacFFlessThan3 = dojo.isFF && dojo.isFF < 3
|
||||
&& navigator.appVersion.indexOf("Macintosh") != -1;
|
||||
if(!isMacFFlessThan3 || e.detail != 0 || this._seenKeydown){
|
||||
this._onArrowClick(e);
|
||||
}
|
||||
this._seenKeydown = false;
|
||||
},
|
||||
|
||||
_onDropDownKeydown: function(/*Event*/ e){
|
||||
this._seenKeydown = true;
|
||||
},
|
||||
|
||||
_onDropDownBlur: function(/*Event*/ e){
|
||||
this._seenKeydown = false;
|
||||
},
|
||||
|
||||
_onKey: function(/*Event*/ e){
|
||||
// summary: callback when the user presses a key on menu popup node
|
||||
if(this.disabled){ return; }
|
||||
if(e.keyCode == dojo.keys.DOWN_ARROW){
|
||||
if(!this.dropDown || this.dropDown.domNode.style.display=="none"){
|
||||
dojo.stopEvent(e);
|
||||
return this._toggleDropDown();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
// summary: called magically when focus has shifted away from this widget and it's dropdown
|
||||
this._closeDropDown();
|
||||
// don't focus on button. the user has explicitly focused on something else.
|
||||
},
|
||||
|
||||
_toggleDropDown: function(){
|
||||
// summary: toggle the drop-down widget; if it is up, close it, if not, open it
|
||||
if(this.disabled){ return; }
|
||||
dijit.focus(this.popupStateNode);
|
||||
var dropDown = this.dropDown;
|
||||
if(!dropDown){ return false; }
|
||||
if(!dropDown.isShowingNow){
|
||||
// If there's an href, then load that first, so we don't get a flicker
|
||||
if(dropDown.href && !dropDown.isLoaded){
|
||||
var self = this;
|
||||
var handler = dojo.connect(dropDown, "onLoad", function(){
|
||||
dojo.disconnect(handler);
|
||||
self._openDropDown();
|
||||
});
|
||||
dropDown._loadCheck(true);
|
||||
return;
|
||||
}else{
|
||||
this._openDropDown();
|
||||
}
|
||||
}else{
|
||||
this._closeDropDown();
|
||||
}
|
||||
},
|
||||
|
||||
_openDropDown: function(){
|
||||
var dropDown = this.dropDown;
|
||||
var oldWidth=dropDown.domNode.style.width;
|
||||
var self = this;
|
||||
|
||||
dijit.popup.open({
|
||||
parent: this,
|
||||
popup: dropDown,
|
||||
around: this.domNode,
|
||||
orient: this.isLeftToRight() ? {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'}
|
||||
: {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'},
|
||||
onExecute: function(){
|
||||
self._closeDropDown(true);
|
||||
},
|
||||
onCancel: function(){
|
||||
self._closeDropDown(true);
|
||||
},
|
||||
onClose: function(){
|
||||
dropDown.domNode.style.width = oldWidth;
|
||||
self.popupStateNode.removeAttribute("popupActive");
|
||||
this._opened = false;
|
||||
}
|
||||
});
|
||||
if(this.domNode.offsetWidth > dropDown.domNode.offsetWidth){
|
||||
var adjustNode = null;
|
||||
if(!this.isLeftToRight()){
|
||||
adjustNode = dropDown.domNode.parentNode;
|
||||
var oldRight = adjustNode.offsetLeft + adjustNode.offsetWidth;
|
||||
}
|
||||
// make menu at least as wide as the button
|
||||
dojo.marginBox(dropDown.domNode, {w: this.domNode.offsetWidth});
|
||||
if(adjustNode){
|
||||
adjustNode.style.left = oldRight - this.domNode.offsetWidth + "px";
|
||||
}
|
||||
}
|
||||
this.popupStateNode.setAttribute("popupActive", "true");
|
||||
this._opened=true;
|
||||
if(dropDown.focus){
|
||||
dropDown.focus();
|
||||
}
|
||||
// TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
|
||||
},
|
||||
|
||||
_closeDropDown: function(/*Boolean*/ focus){
|
||||
if(this._opened){
|
||||
dijit.popup.close(this.dropDown);
|
||||
if(focus){ this.focus(); }
|
||||
this._opened = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* usage
|
||||
* <button dojoType="ComboButton" onClick="..."><span>Hello world</span><div dojoType=dijit.Menu>...</div></button>
|
||||
*
|
||||
* var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"});
|
||||
* dojo.body().appendChild(button1.domNode);
|
||||
*/
|
||||
dojo.declare("dijit.form.ComboButton", dijit.form.DropDownButton, {
|
||||
// summary
|
||||
// left side is normal button, right side displays menu
|
||||
templateString:"<table class='dijit dijitReset dijitInline dijitLeft'\n\tcellspacing='0' cellpadding='0'\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse,onmousedown:_onMouse\">\n\t<tr>\n\t\t<td\tclass=\"dijitStretch dijitButtonContents dijitButtonNode\"\n\t\t\ttabIndex=\"${tabIndex}\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onButtonClick\" dojoAttachPoint=\"titleNode\"\n\t\t\twaiRole=\"button\" waiState=\"labelledby-${id}_label\">\n\t\t\t<div class=\"dijitInline ${iconClass}\" dojoAttachPoint=\"iconNode\"></div>\n\t\t\t<span class=\"dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\">${label}</span>\n\t\t</td>\n\t\t<td class='dijitReset dijitRight dijitButtonNode dijitDownArrowButton'\n\t\t\tdojoAttachPoint=\"popupStateNode,focusNode\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onArrowClick, onkeypress:_onKey\"\n\t\t\tstateModifier=\"DownArrow\"\n\t\t\ttitle=\"${optionsTitle}\" name=\"${name}\"\n\t\t\twaiRole=\"button\" waiState=\"haspopup-true\"\n\t\t><div waiRole=\"presentation\">▼</div>\n\t</td></tr>\n</table>\n",
|
||||
|
||||
attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
|
||||
{id:"", name:""}),
|
||||
|
||||
// optionsTitle: String
|
||||
// text that describes the options menu (accessibility)
|
||||
optionsTitle: "",
|
||||
|
||||
baseClass: "dijitComboButton",
|
||||
|
||||
_focusedNode: null,
|
||||
|
||||
postCreate: function(){
|
||||
this.inherited(arguments);
|
||||
this._focalNodes = [this.titleNode, this.popupStateNode];
|
||||
dojo.forEach(this._focalNodes, dojo.hitch(this, function(node){
|
||||
if(dojo.isIE){
|
||||
this.connect(node, "onactivate", this._onNodeFocus);
|
||||
}else{
|
||||
this.connect(node, "onfocus", this._onNodeFocus);
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
focusFocalNode: function(node){
|
||||
// summary: Focus the focal node node.
|
||||
this._focusedNode = node;
|
||||
dijit.focus(node);
|
||||
},
|
||||
|
||||
hasNextFocalNode: function(){
|
||||
// summary: Returns true if this widget has no node currently
|
||||
// focused or if there is a node following the focused one.
|
||||
// False is returned if the last node has focus.
|
||||
return this._focusedNode !== this.getFocalNodes()[1];
|
||||
},
|
||||
|
||||
focusNext: function(){
|
||||
// summary: Focus the focal node following the current node with focus
|
||||
// or the first one if no node currently has focus.
|
||||
this._focusedNode = this.getFocalNodes()[this._focusedNode ? 1 : 0];
|
||||
dijit.focus(this._focusedNode);
|
||||
},
|
||||
|
||||
hasPrevFocalNode: function(){
|
||||
// summary: Returns true if this widget has no node currently
|
||||
// focused or if there is a node before the focused one.
|
||||
// False is returned if the first node has focus.
|
||||
return this._focusedNode !== this.getFocalNodes()[0];
|
||||
},
|
||||
|
||||
focusPrev: function(){
|
||||
// summary: Focus the focal node before the current node with focus
|
||||
// or the last one if no node currently has focus.
|
||||
this._focusedNode = this.getFocalNodes()[this._focusedNode ? 0 : 1];
|
||||
dijit.focus(this._focusedNode);
|
||||
},
|
||||
|
||||
getFocalNodes: function(){
|
||||
// summary: Returns an array of focal nodes for this widget.
|
||||
return this._focalNodes;
|
||||
},
|
||||
|
||||
_onNodeFocus: function(evt){
|
||||
this._focusedNode = evt.currentTarget;
|
||||
},
|
||||
|
||||
_onBlur: function(evt){
|
||||
this.inherited(arguments);
|
||||
this._focusedNode = null;
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare("dijit.form.ToggleButton", dijit.form.Button, {
|
||||
// summary
|
||||
// A button that can be in two states (checked or not).
|
||||
// Can be base class for things like tabs or checkbox or radio buttons
|
||||
|
||||
baseClass: "dijitToggleButton",
|
||||
|
||||
// checked: Boolean
|
||||
// Corresponds to the native HTML <input> element's attribute.
|
||||
// In markup, specified as "checked='checked'" or just "checked".
|
||||
// True if the button is depressed, or the checkbox is checked,
|
||||
// or the radio button is selected, etc.
|
||||
checked: false,
|
||||
|
||||
_clicked: function(/*Event*/ evt){
|
||||
this.setChecked(!this.checked);
|
||||
},
|
||||
|
||||
setChecked: function(/*Boolean*/ checked){
|
||||
// summary
|
||||
// Programatically deselect the button
|
||||
this.checked = checked;
|
||||
dijit.setWaiState(this.focusNode || this.domNode, "pressed", this.checked);
|
||||
this._setStateClass();
|
||||
this.onChange(checked);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.CheckBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.CheckBox"] = true;
|
||||
dojo.provide("dijit.form.CheckBox");
|
||||
|
||||
dojo.require("dijit.form.Button");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.CheckBox",
|
||||
dijit.form.ToggleButton,
|
||||
{
|
||||
// summary:
|
||||
// Same as an HTML checkbox, but with fancy styling.
|
||||
//
|
||||
// description:
|
||||
// User interacts with real html inputs.
|
||||
// On onclick (which occurs by mouse click, space-bar, or
|
||||
// using the arrow keys to switch the selected radio button),
|
||||
// we update the state of the checkbox/radio.
|
||||
//
|
||||
// There are two modes:
|
||||
// 1. High contrast mode
|
||||
// 2. Normal mode
|
||||
// In case 1, the regular html inputs are shown and used by the user.
|
||||
// In case 2, the regular html inputs are invisible but still used by
|
||||
// the user. They are turned quasi-invisible and overlay the background-image.
|
||||
|
||||
templateString:"<fieldset class=\"dijitReset dijitInline\" waiRole=\"presentation\"\n\t><input\n\t \ttype=\"${type}\" name=\"${name}\"\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdojoAttachPoint=\"inputNode,focusNode\"\n\t \tdojoAttachEvent=\"onmouseover:_onMouse,onmouseout:_onMouse,onclick:_onClick\"\n/></fieldset>\n",
|
||||
|
||||
baseClass: "dijitCheckBox",
|
||||
|
||||
// Value of "type" attribute for <input>
|
||||
type: "checkbox",
|
||||
|
||||
// value: Value
|
||||
// equivalent to value field on normal checkbox (if checked, the value is passed as
|
||||
// the value when form is submitted)
|
||||
value: "on",
|
||||
|
||||
postCreate: function(){
|
||||
dojo.setSelectable(this.inputNode, false);
|
||||
this.setChecked(this.checked);
|
||||
this.inherited(arguments);
|
||||
},
|
||||
|
||||
setChecked: function(/*Boolean*/ checked){
|
||||
if(dojo.isIE){
|
||||
if(checked){ this.inputNode.setAttribute('checked', 'checked'); }
|
||||
else{ this.inputNode.removeAttribute('checked'); }
|
||||
}else{ this.inputNode.checked = checked; }
|
||||
this.inherited(arguments);
|
||||
},
|
||||
|
||||
setValue: function(/*String*/ value){
|
||||
if(value == null){ value = ""; }
|
||||
this.inputNode.value = value;
|
||||
dijit.form.CheckBox.superclass.setValue.call(this,value);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.RadioButton",
|
||||
dijit.form.CheckBox,
|
||||
{
|
||||
// summary:
|
||||
// Same as an HTML radio, but with fancy styling.
|
||||
//
|
||||
// description:
|
||||
// Implementation details
|
||||
//
|
||||
// Specialization:
|
||||
// We keep track of dijit radio groups so that we can update the state
|
||||
// of all the siblings (the "context") in a group based on input
|
||||
// events. We don't rely on browser radio grouping.
|
||||
|
||||
type: "radio",
|
||||
baseClass: "dijitRadio",
|
||||
|
||||
// This shared object keeps track of all widgets, grouped by name
|
||||
_groups: {},
|
||||
|
||||
postCreate: function(){
|
||||
// add this widget to _groups
|
||||
(this._groups[this.name] = this._groups[this.name] || []).push(this);
|
||||
|
||||
this.inherited(arguments);
|
||||
},
|
||||
|
||||
uninitialize: function(){
|
||||
// remove this widget from _groups
|
||||
dojo.forEach(this._groups[this.name], function(widget, i, arr){
|
||||
if(widget === this){
|
||||
arr.splice(i, 1);
|
||||
return;
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
setChecked: function(/*Boolean*/ checked){
|
||||
// If I am being checked then have to deselect currently checked radio button
|
||||
if(checked){
|
||||
dojo.forEach(this._groups[this.name], function(widget){
|
||||
if(widget != this && widget.checked){
|
||||
widget.setChecked(false);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
this.inherited(arguments);
|
||||
},
|
||||
|
||||
_clicked: function(/*Event*/ e){
|
||||
if(!this.checked){
|
||||
this.setChecked(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,843 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.ComboBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.ComboBox"] = true;
|
||||
dojo.provide("dijit.form.ComboBox");
|
||||
|
||||
dojo.require("dojo.data.ItemFileReadStore");
|
||||
dojo.require("dijit.form.ValidationTextBox");
|
||||
dojo.requireLocalization("dijit.form", "ComboBox", null, "ko,zh,ja,zh-tw,ru,it,hu,ROOT,fr,pt,pl,es,de,cs");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.ComboBoxMixin",
|
||||
null,
|
||||
{
|
||||
// summary:
|
||||
// Auto-completing text box, and base class for FilteringSelect widget.
|
||||
//
|
||||
// The drop down box's values are populated from an class called
|
||||
// a data provider, which returns a list of values based on the characters
|
||||
// that the user has typed into the input box.
|
||||
//
|
||||
// Some of the options to the ComboBox are actually arguments to the data
|
||||
// provider.
|
||||
//
|
||||
// You can assume that all the form widgets (and thus anything that mixes
|
||||
// in ComboBoxMixin) will inherit from _FormWidget and thus the "this"
|
||||
// reference will also "be a" _FormWidget.
|
||||
|
||||
// item: Object
|
||||
// This is the item returned by the dojo.data.store implementation that
|
||||
// provides the data for this cobobox, it's the currently selected item.
|
||||
item: null,
|
||||
|
||||
// pageSize: Integer
|
||||
// Argument to data provider.
|
||||
// Specifies number of search results per page (before hitting "next" button)
|
||||
pageSize: Infinity,
|
||||
|
||||
// store: Object
|
||||
// Reference to data provider object used by this ComboBox
|
||||
store: null,
|
||||
|
||||
// query: Object
|
||||
// A query that can be passed to 'store' to initially filter the items,
|
||||
// before doing further filtering based on searchAttr and the key.
|
||||
query: {},
|
||||
|
||||
// autoComplete: Boolean
|
||||
// If you type in a partial string, and then tab out of the <input> box,
|
||||
// automatically copy the first entry displayed in the drop down list to
|
||||
// the <input> field
|
||||
autoComplete: true,
|
||||
|
||||
// searchDelay: Integer
|
||||
// Delay in milliseconds between when user types something and we start
|
||||
// searching based on that value
|
||||
searchDelay: 100,
|
||||
|
||||
// searchAttr: String
|
||||
// Searches pattern match against this field
|
||||
searchAttr: "name",
|
||||
|
||||
// ignoreCase: Boolean
|
||||
// Set true if the ComboBox should ignore case when matching possible items
|
||||
ignoreCase: true,
|
||||
|
||||
// hasDownArrow: Boolean
|
||||
// Set this textbox to have a down arrow button.
|
||||
// Defaults to true.
|
||||
hasDownArrow:true,
|
||||
|
||||
// _hasFocus: Boolean
|
||||
// Represents focus state of the textbox
|
||||
// TODO: get rid of this; it's unnecessary (but currently referenced in FilteringSelect)
|
||||
_hasFocus:false,
|
||||
|
||||
templateString:"<table style=\"display: -moz-inline-stack;\" class=\"dijit dijitReset dijitInlineTable dijitLeft\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\" dojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\" waiRole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td class='dijitReset dijitStretch dijitInputField' width=\"100%\"\n\t\t\t><input type=\"text\" autocomplete=\"off\" name=\"${name}\"\n\t\t\tdojoAttachEvent=\"onkeypress, onkeyup, onfocus, onblur, compositionend\"\n\t\t\tdojoAttachPoint=\"textbox,focusNode\" waiRole=\"combobox\"\n\t\t/></td\n\t\t><td class=\"dijitReset dijitValidationIconField\" width=\"0%\"\n\t\t\t><div dojoAttachPoint='iconNode' class='dijitValidationIcon'></div><div class='dijitInline dijitValidationIconText'>Χ</div\n\t\t></td\n\t\t><td class='dijitReset dijitRight dijitButtonNode dijitDownArrowButton' width=\"0%\"\n\t\t\tdojoAttachPoint=\"downArrowNode\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onArrowClick,onmousedown:_onArrowMouseDown,onmouseup:_onMouse,onmouseenter:_onMouse,onmouseleave:_onMouse\"\n\t\t\t><div class=\"dijitDownArrowButtonInner\" waiRole=\"presentation\" tabIndex=\"-1\"\n\t\t\t\t><div class=\"dijitDownArrowButtonChar\">▼</div\n\t\t\t></div\n\t\t></td\t\n\t></tr\n></table>\n",
|
||||
|
||||
baseClass:"dijitComboBox",
|
||||
|
||||
_lastDisplayedValue: "",
|
||||
|
||||
getValue:function(){
|
||||
// don't get the textbox value but rather the previously set hidden value
|
||||
return dijit.form.TextBox.superclass.getValue.apply(this, arguments);
|
||||
},
|
||||
|
||||
setDisplayedValue:function(/*String*/ value){
|
||||
this._lastDisplayedValue = value;
|
||||
this.setValue(value, true);
|
||||
},
|
||||
|
||||
_getCaretPos: function(/*DomNode*/ element){
|
||||
// khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
|
||||
if(typeof(element.selectionStart)=="number"){
|
||||
// FIXME: this is totally borked on Moz < 1.3. Any recourse?
|
||||
return element.selectionStart;
|
||||
}else if(dojo.isIE){
|
||||
// in the case of a mouse click in a popup being handled,
|
||||
// then the document.selection is not the textarea, but the popup
|
||||
// var r = document.selection.createRange();
|
||||
// hack to get IE 6 to play nice. What a POS browser.
|
||||
var tr = document.selection.createRange().duplicate();
|
||||
var ntr = element.createTextRange();
|
||||
tr.move("character",0);
|
||||
ntr.move("character",0);
|
||||
try{
|
||||
// If control doesnt have focus, you get an exception.
|
||||
// Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
|
||||
// There appears to be no workaround for this - googled for quite a while.
|
||||
ntr.setEndPoint("EndToEnd", tr);
|
||||
return String(ntr.text).replace(/\r/g,"").length;
|
||||
}catch(e){
|
||||
return 0; // If focus has shifted, 0 is fine for caret pos.
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_setCaretPos: function(/*DomNode*/ element, /*Number*/ location){
|
||||
location = parseInt(location);
|
||||
this._setSelectedRange(element, location, location);
|
||||
},
|
||||
|
||||
_setSelectedRange: function(/*DomNode*/ element, /*Number*/ start, /*Number*/ end){
|
||||
if(!end){
|
||||
end = element.value.length;
|
||||
} // NOTE: Strange - should be able to put caret at start of text?
|
||||
// Mozilla
|
||||
// parts borrowed from http://www.faqts.com/knowledge_base/view.phtml/aid/13562/fid/130
|
||||
if(element.setSelectionRange){
|
||||
dijit.focus(element);
|
||||
element.setSelectionRange(start, end);
|
||||
}else if(element.createTextRange){ // IE
|
||||
var range = element.createTextRange();
|
||||
with(range){
|
||||
collapse(true);
|
||||
moveEnd('character', end);
|
||||
moveStart('character', start);
|
||||
select();
|
||||
}
|
||||
}else{ //otherwise try the event-creation hack (our own invention)
|
||||
// do we need these?
|
||||
element.value = element.value;
|
||||
element.blur();
|
||||
dijit.focus(element);
|
||||
// figure out how far back to go
|
||||
var dist = parseInt(element.value.length)-end;
|
||||
var tchar = String.fromCharCode(37);
|
||||
var tcc = tchar.charCodeAt(0);
|
||||
for(var x = 0; x < dist; x++){
|
||||
var te = document.createEvent("KeyEvents");
|
||||
te.initKeyEvent("keypress", true, true, null, false, false, false, false, tcc, tcc);
|
||||
element.dispatchEvent(te);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onkeypress: function(/*Event*/ evt){
|
||||
// summary: handles keyboard events
|
||||
|
||||
//except for pasting case - ctrl + v(118)
|
||||
if(evt.altKey || (evt.ctrlKey && evt.charCode != 118)){
|
||||
return;
|
||||
}
|
||||
var doSearch = false;
|
||||
this.item = null; // #4872
|
||||
if(this._isShowingNow){this._popupWidget.handleKey(evt);}
|
||||
switch(evt.keyCode){
|
||||
case dojo.keys.PAGE_DOWN:
|
||||
case dojo.keys.DOWN_ARROW:
|
||||
if(!this._isShowingNow||this._prev_key_esc){
|
||||
this._arrowPressed();
|
||||
doSearch=true;
|
||||
}else{
|
||||
this._announceOption(this._popupWidget.getHighlightedOption());
|
||||
}
|
||||
dojo.stopEvent(evt);
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = false;
|
||||
break;
|
||||
|
||||
case dojo.keys.PAGE_UP:
|
||||
case dojo.keys.UP_ARROW:
|
||||
if(this._isShowingNow){
|
||||
this._announceOption(this._popupWidget.getHighlightedOption());
|
||||
}
|
||||
dojo.stopEvent(evt);
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = false;
|
||||
break;
|
||||
|
||||
case dojo.keys.ENTER:
|
||||
// prevent submitting form if user presses enter
|
||||
// also prevent accepting the value if either Next or Previous are selected
|
||||
var highlighted;
|
||||
if(this._isShowingNow&&(highlighted=this._popupWidget.getHighlightedOption())){
|
||||
// only stop event on prev/next
|
||||
if(highlighted==this._popupWidget.nextButton){
|
||||
this._nextSearch(1);
|
||||
dojo.stopEvent(evt);
|
||||
break;
|
||||
}
|
||||
else if(highlighted==this._popupWidget.previousButton){
|
||||
this._nextSearch(-1);
|
||||
dojo.stopEvent(evt);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
this.setDisplayedValue(this.getDisplayedValue());
|
||||
}
|
||||
// default case:
|
||||
// prevent submit, but allow event to bubble
|
||||
evt.preventDefault();
|
||||
// fall through
|
||||
|
||||
case dojo.keys.TAB:
|
||||
var newvalue=this.getDisplayedValue();
|
||||
// #4617: if the user had More Choices selected fall into the _onBlur handler
|
||||
if(this._popupWidget &&
|
||||
(newvalue == this._popupWidget._messages["previousMessage"] ||
|
||||
newvalue == this._popupWidget._messages["nextMessage"])){
|
||||
break;
|
||||
}
|
||||
if(this._isShowingNow){
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = false;
|
||||
if(this._popupWidget.getHighlightedOption()){
|
||||
this._popupWidget.setValue({target:this._popupWidget.getHighlightedOption()}, true);
|
||||
}
|
||||
this._hideResultList();
|
||||
}
|
||||
break;
|
||||
|
||||
case dojo.keys.SPACE:
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = false;
|
||||
if(this._isShowingNow && this._popupWidget.getHighlightedOption()){
|
||||
dojo.stopEvent(evt);
|
||||
this._selectOption();
|
||||
this._hideResultList();
|
||||
}else{
|
||||
doSearch = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case dojo.keys.ESCAPE:
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = true;
|
||||
this._hideResultList();
|
||||
if(this._lastDisplayedValue != this.getDisplayedValue()){
|
||||
this.setDisplayedValue(this._lastDisplayedValue);
|
||||
dojo.stopEvent(evt);
|
||||
}else{
|
||||
this.setValue(this.getValue());
|
||||
}
|
||||
break;
|
||||
|
||||
case dojo.keys.DELETE:
|
||||
case dojo.keys.BACKSPACE:
|
||||
this._prev_key_esc = false;
|
||||
this._prev_key_backspace = true;
|
||||
doSearch = true;
|
||||
break;
|
||||
|
||||
case dojo.keys.RIGHT_ARROW: // fall through
|
||||
|
||||
case dojo.keys.LEFT_ARROW: // fall through
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = false;
|
||||
break;
|
||||
|
||||
default:// non char keys (F1-F12 etc..) shouldn't open list
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = false;
|
||||
if(dojo.isIE || evt.charCode != 0){
|
||||
doSearch=true;
|
||||
}
|
||||
}
|
||||
if(this.searchTimer){
|
||||
clearTimeout(this.searchTimer);
|
||||
}
|
||||
if(doSearch){
|
||||
// need to wait a tad before start search so that the event bubbles through DOM and we have value visible
|
||||
this.searchTimer = setTimeout(dojo.hitch(this, this._startSearchFromInput), this.searchDelay);
|
||||
}
|
||||
},
|
||||
|
||||
_autoCompleteText: function(/*String*/ text){
|
||||
// summary:
|
||||
// Fill in the textbox with the first item from the drop down list, and
|
||||
// highlight the characters that were auto-completed. For example, if user
|
||||
// typed "CA" and the drop down list appeared, the textbox would be changed to
|
||||
// "California" and "ifornia" would be highlighted.
|
||||
|
||||
// IE7: clear selection so next highlight works all the time
|
||||
this._setSelectedRange(this.focusNode, this.focusNode.value.length, this.focusNode.value.length);
|
||||
// does text autoComplete the value in the textbox?
|
||||
// #3744: escape regexp so the user's input isn't treated as a regular expression.
|
||||
// Example: If the user typed "(" then the regexp would throw "unterminated parenthetical."
|
||||
// Also see #2558 for the autocompletion bug this regular expression fixes.
|
||||
if(new RegExp("^"+escape(this.focusNode.value), this.ignoreCase ? "i" : "").test(escape(text))){
|
||||
var cpos = this._getCaretPos(this.focusNode);
|
||||
// only try to extend if we added the last character at the end of the input
|
||||
if((cpos+1) > this.focusNode.value.length){
|
||||
// only add to input node as we would overwrite Capitalisation of chars
|
||||
// actually, that is ok
|
||||
this.focusNode.value = text;//.substr(cpos);
|
||||
// visually highlight the autocompleted characters
|
||||
this._setSelectedRange(this.focusNode, cpos, this.focusNode.value.length);
|
||||
dijit.setWaiState(this.focusNode, "valuenow", text);
|
||||
}
|
||||
}else{
|
||||
// text does not autoComplete; replace the whole value and highlight
|
||||
this.focusNode.value = text;
|
||||
this._setSelectedRange(this.focusNode, 0, this.focusNode.value.length);
|
||||
dijit.setWaiState(this.focusNode, "valuenow", text);
|
||||
}
|
||||
},
|
||||
|
||||
_openResultList: function(/*Object*/ results, /*Object*/ dataObject){
|
||||
if(this.disabled || dataObject.query[this.searchAttr] != this._lastQuery){
|
||||
return;
|
||||
}
|
||||
this._popupWidget.clearResultList();
|
||||
if(!results.length){
|
||||
this._hideResultList();
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill in the textbox with the first item from the drop down list, and
|
||||
// highlight the characters that were auto-completed. For example, if user
|
||||
// typed "CA" and the drop down list appeared, the textbox would be changed to
|
||||
// "California" and "ifornia" would be highlighted.
|
||||
|
||||
var zerothvalue=new String(this.store.getValue(results[0], this.searchAttr));
|
||||
if(zerothvalue && this.autoComplete && !this._prev_key_backspace &&
|
||||
// when the user clicks the arrow button to show the full list,
|
||||
// startSearch looks for "*".
|
||||
// it does not make sense to autocomplete
|
||||
// if they are just previewing the options available.
|
||||
(dataObject.query[this.searchAttr] != "*")){
|
||||
this._autoCompleteText(zerothvalue);
|
||||
// announce the autocompleted value
|
||||
dijit.setWaiState(this.focusNode || this.domNode, "valuenow", zerothvalue);
|
||||
}
|
||||
this._popupWidget.createOptions(results, dataObject, dojo.hitch(this, this._getMenuLabelFromItem));
|
||||
|
||||
// show our list (only if we have content, else nothing)
|
||||
this._showResultList();
|
||||
|
||||
// #4091: tell the screen reader that the paging callback finished by shouting the next choice
|
||||
if(dataObject.direction){
|
||||
if(dataObject.direction==1){
|
||||
this._popupWidget.highlightFirstOption();
|
||||
}else if(dataObject.direction==-1){
|
||||
this._popupWidget.highlightLastOption();
|
||||
}
|
||||
this._announceOption(this._popupWidget.getHighlightedOption());
|
||||
}
|
||||
},
|
||||
|
||||
_showResultList: function(){
|
||||
this._hideResultList();
|
||||
var items = this._popupWidget.getItems(),
|
||||
visibleCount = Math.min(items.length,this.maxListLength);
|
||||
this._arrowPressed();
|
||||
// hide the tooltip
|
||||
this._displayMessage("");
|
||||
|
||||
// Position the list and if it's too big to fit on the screen then
|
||||
// size it to the maximum possible height
|
||||
// Our dear friend IE doesnt take max-height so we need to calculate that on our own every time
|
||||
// TODO: want to redo this, see http://trac.dojotoolkit.org/ticket/3272, http://trac.dojotoolkit.org/ticket/4108
|
||||
with(this._popupWidget.domNode.style){
|
||||
// natural size of the list has changed, so erase old width/height settings,
|
||||
// which were hardcoded in a previous call to this function (via dojo.marginBox() call)
|
||||
width="";
|
||||
height="";
|
||||
}
|
||||
var best=this.open();
|
||||
// #3212: only set auto scroll bars if necessary
|
||||
// prevents issues with scroll bars appearing when they shouldn't when node is made wider (fractional pixels cause this)
|
||||
var popupbox=dojo.marginBox(this._popupWidget.domNode);
|
||||
this._popupWidget.domNode.style.overflow=((best.h==popupbox.h)&&(best.w==popupbox.w))?"hidden":"auto";
|
||||
// #4134: borrow TextArea scrollbar test so content isn't covered by scrollbar and horizontal scrollbar doesn't appear
|
||||
var newwidth=best.w;
|
||||
if(best.h<this._popupWidget.domNode.scrollHeight){newwidth+=16;}
|
||||
dojo.marginBox(this._popupWidget.domNode, {h:best.h,w:Math.max(newwidth,this.domNode.offsetWidth)});
|
||||
},
|
||||
|
||||
_hideResultList: function(){
|
||||
if(this._isShowingNow){
|
||||
dijit.popup.close(this._popupWidget);
|
||||
this._arrowIdle();
|
||||
this._isShowingNow=false;
|
||||
}
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
// summary: called magically when focus has shifted away from this widget and it's dropdown
|
||||
this._hasFocus=false;
|
||||
this._hasBeenBlurred = true;
|
||||
this._hideResultList();
|
||||
// if the user clicks away from the textbox OR tabs away, set the value to the textbox value
|
||||
// #4617: if value is now more choices or previous choices, revert the value
|
||||
var newvalue=this.getDisplayedValue();
|
||||
if(this._popupWidget&&(newvalue==this._popupWidget._messages["previousMessage"]||newvalue==this._popupWidget._messages["nextMessage"])){
|
||||
this.setValue(this._lastValueReported);
|
||||
}else{
|
||||
this.setDisplayedValue(newvalue);
|
||||
}
|
||||
},
|
||||
|
||||
onfocus:function(/*Event*/ evt){
|
||||
this._hasFocus=true;
|
||||
|
||||
// update styling to reflect that we are focused
|
||||
this._onMouse(evt);
|
||||
},
|
||||
|
||||
onblur:function(/*Event*/ evt){ /* not _onBlur! */
|
||||
this._arrowIdle();
|
||||
|
||||
// hide the Tooltip
|
||||
// TODO: isn't this handled by ValidationTextBox?
|
||||
this.validate(false);
|
||||
|
||||
// don't call this since the TextBox setValue is asynchronous
|
||||
// if you uncomment this line, when you click away from the textbox,
|
||||
// the value in the textbox reverts to match the hidden value
|
||||
//this.parentClass.onblur.apply(this, arguments);
|
||||
|
||||
// update styling since we are no longer focused
|
||||
this._onMouse(evt);
|
||||
},
|
||||
|
||||
_announceOption: function(/*Node*/ node){
|
||||
// summary:
|
||||
// a11y code that puts the highlighted option in the textbox
|
||||
// This way screen readers will know what is happening in the menu
|
||||
|
||||
if(node==null){return;}
|
||||
// pull the text value from the item attached to the DOM node
|
||||
var newValue;
|
||||
if(node==this._popupWidget.nextButton||node==this._popupWidget.previousButton){
|
||||
newValue=node.innerHTML;
|
||||
}else{
|
||||
newValue=this.store.getValue(node.item, this.searchAttr);
|
||||
}
|
||||
// get the text that the user manually entered (cut off autocompleted text)
|
||||
this.focusNode.value=this.focusNode.value.substring(0, this._getCaretPos(this.focusNode));
|
||||
// autocomplete the rest of the option to announce change
|
||||
this._autoCompleteText(newValue);
|
||||
},
|
||||
|
||||
_selectOption: function(/*Event*/ evt){
|
||||
var tgt = null;
|
||||
if(!evt){
|
||||
evt ={ target: this._popupWidget.getHighlightedOption()};
|
||||
}
|
||||
// what if nothing is highlighted yet?
|
||||
if(!evt.target){
|
||||
// handle autocompletion where the the user has hit ENTER or TAB
|
||||
this.setDisplayedValue(this.getDisplayedValue());
|
||||
return;
|
||||
// otherwise the user has accepted the autocompleted value
|
||||
}else{
|
||||
tgt = evt.target;
|
||||
}
|
||||
if(!evt.noHide){
|
||||
this._hideResultList();
|
||||
this._setCaretPos(this.focusNode, this.store.getValue(tgt.item, this.searchAttr).length);
|
||||
}
|
||||
this._doSelect(tgt);
|
||||
},
|
||||
|
||||
_doSelect: function(tgt){
|
||||
this.item = tgt.item;
|
||||
this.setValue(this.store.getValue(tgt.item, this.searchAttr), true);
|
||||
},
|
||||
|
||||
_onArrowClick: function(){
|
||||
// summary: callback when arrow is clicked
|
||||
if(this.disabled){
|
||||
return;
|
||||
}
|
||||
this.focus();
|
||||
if(this._isShowingNow){
|
||||
this._hideResultList();
|
||||
}else{
|
||||
// forces full population of results, if they click
|
||||
// on the arrow it means they want to see more options
|
||||
this._startSearch("");
|
||||
}
|
||||
},
|
||||
|
||||
_onArrowMouseDown: function(evt){
|
||||
this._layoutHack(); // hack for FF2, see http://trac.dojotoolkit.org/ticket/5007
|
||||
this._onMouse(evt);
|
||||
},
|
||||
|
||||
_startSearchFromInput: function(){
|
||||
this._startSearch(this.focusNode.value);
|
||||
},
|
||||
|
||||
_startSearch: function(/*String*/ key){
|
||||
if(!this._popupWidget){
|
||||
this._popupWidget = new dijit.form._ComboBoxMenu({
|
||||
onChange: dojo.hitch(this, this._selectOption)
|
||||
});
|
||||
}
|
||||
// create a new query to prevent accidentally querying for a hidden value from FilteringSelect's keyField
|
||||
var query=this.query;
|
||||
this._lastQuery=query[this.searchAttr]=key+"*";
|
||||
var dataObject=this.store.fetch({queryOptions:{ignoreCase:this.ignoreCase, deep:true}, query: query, onComplete:dojo.hitch(this, "_openResultList"), start:0, count:this.pageSize});
|
||||
function nextSearch(dataObject, direction){
|
||||
dataObject.start+=dataObject.count*direction;
|
||||
// #4091: tell callback the direction of the paging so the screen reader knows which menu option to shout
|
||||
dataObject.direction=direction;
|
||||
dataObject.store.fetch(dataObject);
|
||||
}
|
||||
this._nextSearch=this._popupWidget.onPage=dojo.hitch(this, nextSearch, dataObject);
|
||||
},
|
||||
|
||||
_getValueField:function(){
|
||||
return this.searchAttr;
|
||||
},
|
||||
|
||||
/////////////// Event handlers /////////////////////
|
||||
|
||||
_arrowPressed: function(){
|
||||
if(!this.disabled&&this.hasDownArrow){
|
||||
dojo.addClass(this.downArrowNode, "dijitArrowButtonActive");
|
||||
}
|
||||
},
|
||||
|
||||
_arrowIdle: function(){
|
||||
if(!this.disabled&&this.hasDownArrow){
|
||||
dojo.removeClass(this.downArrowNode, "dojoArrowButtonPushed");
|
||||
}
|
||||
},
|
||||
|
||||
compositionend: function(/*Event*/ evt){
|
||||
// summary: When inputting characters using an input method, such as Asian
|
||||
// languages, it will generate this event instead of onKeyDown event
|
||||
// Note: this event is only triggered in FF (not in IE)
|
||||
this.onkeypress({charCode:-1});
|
||||
},
|
||||
|
||||
//////////// INITIALIZATION METHODS ///////////////////////////////////////
|
||||
constructor: function(){
|
||||
this.query={};
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
if(!this.hasDownArrow){
|
||||
this.baseClass = "dijitTextBox";
|
||||
}
|
||||
if(!this.store){
|
||||
// if user didn't specify store, then assume there are option tags
|
||||
var items = this.srcNodeRef ? dojo.query("> option", this.srcNodeRef).map(function(node){
|
||||
node.style.display="none";
|
||||
return { value: node.getAttribute("value"), name: String(node.innerHTML) };
|
||||
}) : {};
|
||||
this.store = new dojo.data.ItemFileReadStore({data: {identifier:this._getValueField(), items:items}});
|
||||
|
||||
// if there is no value set and there is an option list,
|
||||
// set the value to the first value to be consistent with native Select
|
||||
if(items && items.length && !this.value){
|
||||
// For <select>, IE does not let you set the value attribute of the srcNodeRef (and thus dojo.mixin does not copy it).
|
||||
// IE does understand selectedIndex though, which is automatically set by the selected attribute of an option tag
|
||||
this.value = items[this.srcNodeRef.selectedIndex != -1 ? this.srcNodeRef.selectedIndex : 0]
|
||||
[this._getValueField()];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
uninitialize:function(){
|
||||
if(this._popupWidget){
|
||||
this._hideResultList();
|
||||
this._popupWidget.destroy()
|
||||
};
|
||||
},
|
||||
|
||||
_getMenuLabelFromItem:function(/*Item*/ item){
|
||||
return {html:false, label:this.store.getValue(item, this.searchAttr)};
|
||||
},
|
||||
|
||||
open:function(){
|
||||
this._isShowingNow=true;
|
||||
return dijit.popup.open({
|
||||
popup: this._popupWidget,
|
||||
around: this.domNode,
|
||||
parent: this
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form._ComboBoxMenu",
|
||||
[dijit._Widget, dijit._Templated],
|
||||
|
||||
{
|
||||
// summary:
|
||||
// Focus-less div based menu for internal use in ComboBox
|
||||
|
||||
templateString:"<div class='dijitMenu' dojoAttachEvent='onclick,onmouseover,onmouseout' tabIndex='-1' style='overflow:\"auto\";'>"
|
||||
+"<div class='dijitMenuItem dijitMenuPreviousButton' dojoAttachPoint='previousButton'></div>"
|
||||
+"<div class='dijitMenuItem dijitMenuNextButton' dojoAttachPoint='nextButton'></div>"
|
||||
+"</div>",
|
||||
_messages:null,
|
||||
|
||||
postMixInProperties:function(){
|
||||
this._messages = dojo.i18n.getLocalization("dijit.form", "ComboBox", this.lang);
|
||||
this.inherited("postMixInProperties", arguments);
|
||||
},
|
||||
|
||||
setValue:function(/*Object*/ value){
|
||||
this.value=value;
|
||||
this.onChange(value);
|
||||
},
|
||||
|
||||
onChange:function(/*Object*/ value){},
|
||||
onPage:function(/*Number*/ direction){},
|
||||
|
||||
postCreate:function(){
|
||||
// fill in template with i18n messages
|
||||
this.previousButton.innerHTML=this._messages["previousMessage"];
|
||||
this.nextButton.innerHTML=this._messages["nextMessage"];
|
||||
this.inherited("postCreate", arguments);
|
||||
},
|
||||
|
||||
onClose:function(){
|
||||
this._blurOptionNode();
|
||||
},
|
||||
|
||||
_createOption:function(/*Object*/ item, labelFunc){
|
||||
// summary: creates an option to appear on the popup menu
|
||||
// subclassed by FilteringSelect
|
||||
|
||||
var labelObject=labelFunc(item);
|
||||
var menuitem = document.createElement("div");
|
||||
if(labelObject.html){menuitem.innerHTML=labelObject.label;}
|
||||
else{menuitem.appendChild(document.createTextNode(labelObject.label));}
|
||||
// #3250: in blank options, assign a normal height
|
||||
if(menuitem.innerHTML==""){
|
||||
menuitem.innerHTML=" "
|
||||
}
|
||||
menuitem.item=item;
|
||||
return menuitem;
|
||||
},
|
||||
|
||||
createOptions:function(results, dataObject, labelFunc){
|
||||
//this._dataObject=dataObject;
|
||||
//this._dataObject.onComplete=dojo.hitch(comboBox, comboBox._openResultList);
|
||||
// display "Previous . . ." button
|
||||
this.previousButton.style.display=dataObject.start==0?"none":"";
|
||||
// create options using _createOption function defined by parent ComboBox (or FilteringSelect) class
|
||||
// #2309: iterate over cache nondestructively
|
||||
var _this=this;
|
||||
dojo.forEach(results, function(item){
|
||||
var menuitem=_this._createOption(item, labelFunc);
|
||||
menuitem.className = "dijitMenuItem";
|
||||
_this.domNode.insertBefore(menuitem, _this.nextButton);
|
||||
});
|
||||
// display "Next . . ." button
|
||||
this.nextButton.style.display=dataObject.count==results.length?"":"none";
|
||||
},
|
||||
|
||||
clearResultList:function(){
|
||||
// keep the previous and next buttons of course
|
||||
while(this.domNode.childNodes.length>2){
|
||||
this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]);
|
||||
}
|
||||
},
|
||||
|
||||
// these functions are called in showResultList
|
||||
getItems:function(){
|
||||
return this.domNode.childNodes;
|
||||
},
|
||||
|
||||
getListLength:function(){
|
||||
return this.domNode.childNodes.length-2;
|
||||
},
|
||||
|
||||
onclick:function(/*Event*/ evt){
|
||||
if(evt.target === this.domNode){
|
||||
return;
|
||||
}else if(evt.target==this.previousButton){
|
||||
this.onPage(-1);
|
||||
}else if(evt.target==this.nextButton){
|
||||
this.onPage(1);
|
||||
}else{
|
||||
var tgt=evt.target;
|
||||
// while the clicked node is inside the div
|
||||
while(!tgt.item){
|
||||
// recurse to the top
|
||||
tgt=tgt.parentNode;
|
||||
}
|
||||
this.setValue({target:tgt}, true);
|
||||
}
|
||||
},
|
||||
|
||||
onmouseover:function(/*Event*/ evt){
|
||||
if(evt.target === this.domNode){ return; }
|
||||
var tgt=evt.target;
|
||||
if(!(tgt==this.previousButton||tgt==this.nextButton)){
|
||||
// while the clicked node is inside the div
|
||||
while(!tgt.item){
|
||||
// recurse to the top
|
||||
tgt=tgt.parentNode;
|
||||
}
|
||||
}
|
||||
this._focusOptionNode(tgt);
|
||||
},
|
||||
|
||||
onmouseout:function(/*Event*/ evt){
|
||||
if(evt.target === this.domNode){ return; }
|
||||
this._blurOptionNode();
|
||||
},
|
||||
|
||||
_focusOptionNode:function(/*DomNode*/ node){
|
||||
// summary:
|
||||
// does the actual highlight
|
||||
if(this._highlighted_option != node){
|
||||
this._blurOptionNode();
|
||||
this._highlighted_option = node;
|
||||
dojo.addClass(this._highlighted_option, "dijitMenuItemHover");
|
||||
}
|
||||
},
|
||||
|
||||
_blurOptionNode:function(){
|
||||
// summary:
|
||||
// removes highlight on highlighted option
|
||||
if(this._highlighted_option){
|
||||
dojo.removeClass(this._highlighted_option, "dijitMenuItemHover");
|
||||
this._highlighted_option = null;
|
||||
}
|
||||
},
|
||||
|
||||
_highlightNextOption:function(){
|
||||
// because each press of a button clears the menu,
|
||||
// the highlighted option sometimes becomes detached from the menu!
|
||||
// test to see if the option has a parent to see if this is the case.
|
||||
if(!this.getHighlightedOption()){
|
||||
this._focusOptionNode(this.domNode.firstChild.style.display=="none"?this.domNode.firstChild.nextSibling:this.domNode.firstChild);
|
||||
}else if(this._highlighted_option.nextSibling&&this._highlighted_option.nextSibling.style.display!="none"){
|
||||
this._focusOptionNode(this._highlighted_option.nextSibling);
|
||||
}
|
||||
// scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseover
|
||||
dijit.scrollIntoView(this._highlighted_option);
|
||||
},
|
||||
|
||||
highlightFirstOption:function(){
|
||||
// highlight the non-Previous choices option
|
||||
this._focusOptionNode(this.domNode.firstChild.nextSibling);
|
||||
dijit.scrollIntoView(this._highlighted_option);
|
||||
},
|
||||
|
||||
highlightLastOption:function(){
|
||||
// highlight the noon-More choices option
|
||||
this._focusOptionNode(this.domNode.lastChild.previousSibling);
|
||||
dijit.scrollIntoView(this._highlighted_option);
|
||||
},
|
||||
|
||||
_highlightPrevOption:function(){
|
||||
// if nothing selected, highlight last option
|
||||
// makes sense if you select Previous and try to keep scrolling up the list
|
||||
if(!this.getHighlightedOption()){
|
||||
this._focusOptionNode(this.domNode.lastChild.style.display=="none"?this.domNode.lastChild.previousSibling:this.domNode.lastChild);
|
||||
}else if(this._highlighted_option.previousSibling&&this._highlighted_option.previousSibling.style.display!="none"){
|
||||
this._focusOptionNode(this._highlighted_option.previousSibling);
|
||||
}
|
||||
dijit.scrollIntoView(this._highlighted_option);
|
||||
},
|
||||
|
||||
_page:function(/*Boolean*/ up){
|
||||
var scrollamount=0;
|
||||
var oldscroll=this.domNode.scrollTop;
|
||||
var height=parseInt(dojo.getComputedStyle(this.domNode).height);
|
||||
// if no item is highlighted, highlight the first option
|
||||
if(!this.getHighlightedOption()){this._highlightNextOption();}
|
||||
while(scrollamount<height){
|
||||
if(up){
|
||||
// stop at option 1
|
||||
if(!this.getHighlightedOption().previousSibling||this._highlighted_option.previousSibling.style.display=="none"){break;}
|
||||
this._highlightPrevOption();
|
||||
}else{
|
||||
// stop at last option
|
||||
if(!this.getHighlightedOption().nextSibling||this._highlighted_option.nextSibling.style.display=="none"){break;}
|
||||
this._highlightNextOption();
|
||||
}
|
||||
// going backwards
|
||||
var newscroll=this.domNode.scrollTop;
|
||||
scrollamount+=(newscroll-oldscroll)*(up ? -1:1);
|
||||
oldscroll=newscroll;
|
||||
}
|
||||
},
|
||||
|
||||
pageUp:function(){
|
||||
this._page(true);
|
||||
},
|
||||
|
||||
pageDown:function(){
|
||||
this._page(false);
|
||||
},
|
||||
|
||||
getHighlightedOption:function(){
|
||||
// summary:
|
||||
// Returns the highlighted option.
|
||||
return this._highlighted_option&&this._highlighted_option.parentNode ? this._highlighted_option : null;
|
||||
},
|
||||
|
||||
handleKey:function(evt){
|
||||
switch(evt.keyCode){
|
||||
case dojo.keys.DOWN_ARROW:
|
||||
this._highlightNextOption();
|
||||
break;
|
||||
case dojo.keys.PAGE_DOWN:
|
||||
this.pageDown();
|
||||
break;
|
||||
case dojo.keys.UP_ARROW:
|
||||
this._highlightPrevOption();
|
||||
break;
|
||||
case dojo.keys.PAGE_UP:
|
||||
this.pageUp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.ComboBox",
|
||||
[dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],
|
||||
{
|
||||
postMixInProperties: function(){
|
||||
dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);
|
||||
dijit.form.ValidationTextBox.prototype.postMixInProperties.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.CurrencyTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.CurrencyTextBox"] = true;
|
||||
dojo.provide("dijit.form.CurrencyTextBox");
|
||||
|
||||
//FIXME: dojo.experimental throws an unreadable exception?
|
||||
//dojo.experimental("dijit.form.CurrencyTextBox");
|
||||
|
||||
dojo.require("dojo.currency");
|
||||
dojo.require("dijit.form.NumberTextBox");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.CurrencyTextBox",
|
||||
dijit.form.NumberTextBox,
|
||||
{
|
||||
// code: String
|
||||
// the ISO4217 currency code, a three letter sequence like "USD"
|
||||
// See http://en.wikipedia.org/wiki/ISO_4217
|
||||
currency: "",
|
||||
|
||||
regExpGen: dojo.currency.regexp,
|
||||
format: dojo.currency.format,
|
||||
parse: dojo.currency.parse,
|
||||
|
||||
postMixInProperties: function(){
|
||||
if(this.constraints === dijit.form.ValidationTextBox.prototype.constraints){
|
||||
// declare a constraints property on 'this' so we don't overwrite the shared default object in 'prototype'
|
||||
this.constraints = {};
|
||||
}
|
||||
this.constraints.currency = this.currency;
|
||||
dijit.form.CurrencyTextBox.superclass.postMixInProperties.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.DateTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.DateTextBox"] = true;
|
||||
dojo.provide("dijit.form.DateTextBox");
|
||||
|
||||
dojo.require("dijit._Calendar");
|
||||
dojo.require("dijit.form.TimeTextBox");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.DateTextBox",
|
||||
dijit.form.TimeTextBox,
|
||||
{
|
||||
// summary:
|
||||
// A validating, serializable, range-bound date text box.
|
||||
|
||||
_popupClass: "dijit._Calendar",
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.inherited('postMixInProperties', arguments);
|
||||
this.constraints.selector = 'date';
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.FilteringSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.FilteringSelect"] = true;
|
||||
dojo.provide("dijit.form.FilteringSelect");
|
||||
|
||||
dojo.require("dijit.form.ComboBox");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.FilteringSelect",
|
||||
[dijit.form.MappedTextBox, dijit.form.ComboBoxMixin],
|
||||
{
|
||||
/*
|
||||
* summary
|
||||
* Enhanced version of HTML's <select> tag.
|
||||
*
|
||||
* Similar features:
|
||||
* - There is a drop down list of possible values.
|
||||
* - You can only enter a value from the drop down list. (You can't enter an arbitrary value.)
|
||||
* - The value submitted with the form is the hidden value (ex: CA),
|
||||
* not the displayed value a.k.a. label (ex: California)
|
||||
*
|
||||
* Enhancements over plain HTML version:
|
||||
* - If you type in some text then it will filter down the list of possible values in the drop down list.
|
||||
* - List can be specified either as a static list or via a javascript function (that can get the list from a server)
|
||||
*/
|
||||
|
||||
// searchAttr: String
|
||||
// Searches pattern match against this field
|
||||
|
||||
// labelAttr: String
|
||||
// Optional. The text that actually appears in the drop down.
|
||||
// If not specified, the searchAttr text is used instead.
|
||||
labelAttr: "",
|
||||
|
||||
// labelType: String
|
||||
// "html" or "text"
|
||||
labelType: "text",
|
||||
|
||||
_isvalid:true,
|
||||
|
||||
isValid:function(){
|
||||
return this._isvalid;
|
||||
},
|
||||
|
||||
_callbackSetLabel: function(/*Array*/ result, /*Object*/ dataObject){
|
||||
// summary
|
||||
// Callback function that dynamically sets the label of the ComboBox
|
||||
|
||||
// setValue does a synchronous lookup,
|
||||
// so it calls _callbackSetLabel directly,
|
||||
// and so does not pass dataObject
|
||||
// dataObject==null means do not test the lastQuery, just continue
|
||||
if(dataObject&&dataObject.query[this.searchAttr]!=this._lastQuery){return;}
|
||||
if(!result.length){
|
||||
//#3268: do nothing on bad input
|
||||
//this._setValue("", "");
|
||||
//#3285: change CSS to indicate error
|
||||
if(!this._hasFocus){ this.valueNode.value=""; }
|
||||
dijit.form.TextBox.superclass.setValue.call(this, undefined, !this._hasFocus);
|
||||
this._isvalid=false;
|
||||
this.validate(this._hasFocus);
|
||||
}else{
|
||||
this._setValueFromItem(result[0]);
|
||||
}
|
||||
},
|
||||
|
||||
_openResultList: function(/*Object*/ results, /*Object*/ dataObject){
|
||||
// #3285: tap into search callback to see if user's query resembles a match
|
||||
if(dataObject.query[this.searchAttr]!=this._lastQuery){return;}
|
||||
this._isvalid=results.length!=0;
|
||||
this.validate(true);
|
||||
dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);
|
||||
},
|
||||
|
||||
getValue:function(){
|
||||
// don't get the textbox value but rather the previously set hidden value
|
||||
return this.valueNode.value;
|
||||
},
|
||||
|
||||
_getValueField:function(){
|
||||
// used for option tag selects
|
||||
return "value";
|
||||
},
|
||||
|
||||
_setValue:function(/*String*/ value, /*String*/ displayedValue){
|
||||
this.valueNode.value = value;
|
||||
dijit.form.FilteringSelect.superclass.setValue.call(this, value, true, displayedValue);
|
||||
this._lastDisplayedValue = displayedValue;
|
||||
},
|
||||
|
||||
setValue: function(/*String*/ value){
|
||||
// summary
|
||||
// Sets the value of the select.
|
||||
// Also sets the label to the corresponding value by reverse lookup.
|
||||
|
||||
//#3347: fetchItemByIdentity if no keyAttr specified
|
||||
var self=this;
|
||||
var handleFetchByIdentity = function(item){
|
||||
if(item){
|
||||
if(self.store.isItemLoaded(item)){
|
||||
self._callbackSetLabel([item]);
|
||||
}else{
|
||||
self.store.loadItem({item:item, onItem: self._callbackSetLabel});
|
||||
}
|
||||
}else{
|
||||
self._isvalid=false;
|
||||
// prevent errors from Tooltip not being created yet
|
||||
self.validate(false);
|
||||
}
|
||||
}
|
||||
this.store.fetchItemByIdentity({identity: value, onItem: handleFetchByIdentity});
|
||||
},
|
||||
|
||||
_setValueFromItem: function(/*item*/ item){
|
||||
// summary
|
||||
// Set the displayed valued in the input box, based on a selected item.
|
||||
// Users shouldn't call this function; they should be calling setDisplayedValue() instead
|
||||
this._isvalid=true;
|
||||
this._setValue(this.store.getIdentity(item), this.labelFunc(item, this.store));
|
||||
},
|
||||
|
||||
labelFunc: function(/*item*/ item, /*dojo.data.store*/ store){
|
||||
// summary: Event handler called when the label changes
|
||||
// returns the label that the ComboBox should display
|
||||
return store.getValue(item, this.searchAttr);
|
||||
},
|
||||
|
||||
onkeyup: function(/*Event*/ evt){
|
||||
// summary: internal function
|
||||
// FilteringSelect needs to wait for the complete label before committing to a reverse lookup
|
||||
//this.setDisplayedValue(this.textbox.value);
|
||||
},
|
||||
|
||||
_doSelect: function(/*Event*/ tgt){
|
||||
// summary:
|
||||
// ComboBox's menu callback function
|
||||
// FilteringSelect overrides this to set both the visible and hidden value from the information stored in the menu
|
||||
this.item = tgt.item;
|
||||
this._setValueFromItem(tgt.item);
|
||||
},
|
||||
|
||||
setDisplayedValue:function(/*String*/ label){
|
||||
// summary:
|
||||
// Set textbox to display label
|
||||
// Also performs reverse lookup to set the hidden value
|
||||
// Used in InlineEditBox
|
||||
|
||||
if(this.store){
|
||||
var query={};
|
||||
this._lastQuery=query[this.searchAttr]=label;
|
||||
// if the label is not valid, the callback will never set it,
|
||||
// so the last valid value will get the warning textbox
|
||||
// set the textbox value now so that the impending warning will make sense to the user
|
||||
this.textbox.value=label;
|
||||
this._lastDisplayedValue=label;
|
||||
this.store.fetch({query:query, queryOptions:{ignoreCase:this.ignoreCase, deep:true}, onComplete: dojo.hitch(this, this._callbackSetLabel)});
|
||||
}
|
||||
},
|
||||
|
||||
_getMenuLabelFromItem:function(/*Item*/ item){
|
||||
// internal function to help ComboBoxMenu figure out what to display
|
||||
if(this.labelAttr){return {html:this.labelType=="html", label:this.store.getValue(item, this.labelAttr)};}
|
||||
else{
|
||||
// because this function is called by ComboBoxMenu, this.inherited tries to find the superclass of ComboBoxMenu
|
||||
return dijit.form.ComboBoxMixin.prototype._getMenuLabelFromItem.apply(this, arguments);
|
||||
}
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
dijit.form.ComboBoxMixin.prototype.postMixInProperties.apply(this, arguments);
|
||||
dijit.form.MappedTextBox.prototype.postMixInProperties.apply(this, arguments);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,283 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.Form"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.Form"] = true;
|
||||
dojo.provide("dijit.form.Form");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare("dijit.form._FormMixin", null,
|
||||
{
|
||||
/*
|
||||
summary:
|
||||
Widget corresponding to <form> tag, for validation and serialization
|
||||
|
||||
usage:
|
||||
<form dojoType="dijit.form.Form" id="myForm">
|
||||
Name: <input type="text" name="name" />
|
||||
</form>
|
||||
myObj={name: "John Doe"};
|
||||
dijit.byId('myForm').setValues(myObj);
|
||||
|
||||
myObj=dijit.byId('myForm').getValues();
|
||||
TODO:
|
||||
* Repeater
|
||||
* better handling for arrays. Often form elements have names with [] like
|
||||
* people[3].sex (for a list of people [{name: Bill, sex: M}, ...])
|
||||
|
||||
*/
|
||||
|
||||
// HTML <FORM> attributes
|
||||
|
||||
action: "",
|
||||
method: "",
|
||||
enctype: "",
|
||||
name: "",
|
||||
"accept-charset": "",
|
||||
accept: "",
|
||||
target: "",
|
||||
|
||||
attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
|
||||
{action: "", method: "", enctype: "", "accept-charset": "", accept: "", target: ""}),
|
||||
|
||||
// execute: Function
|
||||
// User defined function to do stuff when the user hits the submit button
|
||||
execute: function(/*Object*/ formContents){},
|
||||
|
||||
// onCancel: Function
|
||||
// Callback when user has canceled dialog, to notify container
|
||||
// (user shouldn't override)
|
||||
onCancel: function(){},
|
||||
|
||||
// onExecute: Function
|
||||
// Callback when user is about to execute dialog, to notify container
|
||||
// (user shouldn't override)
|
||||
onExecute: function(){},
|
||||
|
||||
templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onsubmit:_onSubmit' name='${name}' enctype='multipart/form-data'></form>",
|
||||
|
||||
_onSubmit: function(/*event*/e) {
|
||||
// summary: callback when user hits submit button
|
||||
dojo.stopEvent(e);
|
||||
this.onExecute(); // notify container that we are about to execute
|
||||
this.execute(this.getValues());
|
||||
},
|
||||
|
||||
submit: function() {
|
||||
// summary: programatically submit form
|
||||
this.containerNode.submit();
|
||||
},
|
||||
|
||||
setValues: function(/*object*/obj) {
|
||||
// summary: fill in form values from a JSON structure
|
||||
|
||||
// generate map from name --> [list of widgets with that name]
|
||||
var map = {};
|
||||
dojo.forEach(this.getDescendants(), function(widget){
|
||||
if(!widget.name){ return; }
|
||||
var entry = map[widget.name] || (map[widget.name] = [] );
|
||||
entry.push(widget);
|
||||
});
|
||||
|
||||
// call setValue() or setChecked() for each widget, according to obj
|
||||
for(var name in map){
|
||||
var widgets = map[name], // array of widgets w/this name
|
||||
values = dojo.getObject(name, false, obj); // list of values for those widgets
|
||||
if(!dojo.isArray(values)){
|
||||
values = [ values ];
|
||||
}
|
||||
if(widgets[0].setChecked){
|
||||
// for checkbox/radio, values is a list of which widgets should be checked
|
||||
dojo.forEach(widgets, function(w, i){
|
||||
w.setChecked(dojo.indexOf(values, w.value) != -1);
|
||||
});
|
||||
}else{
|
||||
// otherwise, values is a list of values to be assigned sequentially to each widget
|
||||
dojo.forEach(widgets, function(w, i){
|
||||
w.setValue(values[i]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets
|
||||
|
||||
dojo.forEach(this.containerNode.elements, function(element){
|
||||
if (element.name == ''){return}; // like "continue"
|
||||
var namePath = element.name.split(".");
|
||||
var myObj=obj;
|
||||
var name=namePath[namePath.length-1];
|
||||
for(var j=1,len2=namePath.length;j<len2;++j) {
|
||||
var p=namePath[j - 1];
|
||||
// repeater support block
|
||||
var nameA=p.split("[");
|
||||
if (nameA.length > 1) {
|
||||
if(typeof(myObj[nameA[0]]) == "undefined") {
|
||||
myObj[nameA[0]]=[ ];
|
||||
} // if
|
||||
|
||||
nameIndex=parseInt(nameA[1]);
|
||||
if(typeof(myObj[nameA[0]][nameIndex]) == "undefined") {
|
||||
myObj[nameA[0]][nameIndex]={};
|
||||
}
|
||||
myObj=myObj[nameA[0]][nameIndex];
|
||||
continue;
|
||||
} // repeater support ends
|
||||
|
||||
if(typeof(myObj[p]) == "undefined") {
|
||||
myObj=undefined;
|
||||
break;
|
||||
};
|
||||
myObj=myObj[p];
|
||||
}
|
||||
|
||||
if (typeof(myObj) == "undefined") {
|
||||
return; // like "continue"
|
||||
}
|
||||
if (typeof(myObj[name]) == "undefined" && this.ignoreNullValues) {
|
||||
return; // like "continue"
|
||||
}
|
||||
|
||||
// TODO: widget values (just call setValue() on the widget)
|
||||
|
||||
switch(element.type) {
|
||||
case "checkbox":
|
||||
element.checked = (name in myObj) &&
|
||||
dojo.some(myObj[name], function(val){ return val==element.value; });
|
||||
break;
|
||||
case "radio":
|
||||
element.checked = (name in myObj) && myObj[name]==element.value;
|
||||
break;
|
||||
case "select-multiple":
|
||||
element.selectedIndex=-1;
|
||||
dojo.forEach(element.options, function(option){
|
||||
option.selected = dojo.some(myObj[name], function(val){ return option.value == val; });
|
||||
});
|
||||
break;
|
||||
case "select-one":
|
||||
element.selectedIndex="0";
|
||||
dojo.forEach(element.options, function(option){
|
||||
option.selected = option.value == myObj[name];
|
||||
});
|
||||
break;
|
||||
case "hidden":
|
||||
case "text":
|
||||
case "textarea":
|
||||
case "password":
|
||||
element.value = myObj[name] || "";
|
||||
break;
|
||||
}
|
||||
});
|
||||
*/
|
||||
},
|
||||
|
||||
getValues: function() {
|
||||
// summary: generate JSON structure from form values
|
||||
|
||||
// get widget values
|
||||
var obj = {};
|
||||
dojo.forEach(this.getDescendants(), function(widget){
|
||||
var value = widget.getValue ? widget.getValue() : widget.value;
|
||||
var name = widget.name;
|
||||
if(!name){ return; }
|
||||
|
||||
// Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays
|
||||
if(widget.setChecked){
|
||||
if(/Radio/.test(widget.declaredClass)){
|
||||
// radio button
|
||||
if(widget.checked){
|
||||
dojo.setObject(name, value, obj);
|
||||
}
|
||||
}else{
|
||||
// checkbox/toggle button
|
||||
var ary=dojo.getObject(name, false, obj);
|
||||
if(!ary){
|
||||
ary=[];
|
||||
dojo.setObject(name, ary, obj);
|
||||
}
|
||||
if(widget.checked){
|
||||
ary.push(value);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// plain input
|
||||
dojo.setObject(name, value, obj);
|
||||
}
|
||||
});
|
||||
|
||||
/***
|
||||
* code for plain input boxes (see also dojo.formToObject, can we use that instead of this code?
|
||||
* but it doesn't understand [] notation, presumably)
|
||||
var obj = { };
|
||||
dojo.forEach(this.containerNode.elements, function(elm){
|
||||
if (!elm.name) {
|
||||
return; // like "continue"
|
||||
}
|
||||
var namePath = elm.name.split(".");
|
||||
var myObj=obj;
|
||||
var name=namePath[namePath.length-1];
|
||||
for(var j=1,len2=namePath.length;j<len2;++j) {
|
||||
var nameIndex = null;
|
||||
var p=namePath[j - 1];
|
||||
var nameA=p.split("[");
|
||||
if (nameA.length > 1) {
|
||||
if(typeof(myObj[nameA[0]]) == "undefined") {
|
||||
myObj[nameA[0]]=[ ];
|
||||
} // if
|
||||
nameIndex=parseInt(nameA[1]);
|
||||
if(typeof(myObj[nameA[0]][nameIndex]) == "undefined") {
|
||||
myObj[nameA[0]][nameIndex]={};
|
||||
}
|
||||
} else if(typeof(myObj[nameA[0]]) == "undefined") {
|
||||
myObj[nameA[0]]={}
|
||||
} // if
|
||||
|
||||
if (nameA.length == 1) {
|
||||
myObj=myObj[nameA[0]];
|
||||
} else {
|
||||
myObj=myObj[nameA[0]][nameIndex];
|
||||
} // if
|
||||
} // for
|
||||
|
||||
if ((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type=="radio" && elm.checked)) {
|
||||
if(name == name.split("[")[0]) {
|
||||
myObj[name]=elm.value;
|
||||
} else {
|
||||
// can not set value when there is no name
|
||||
}
|
||||
} else if (elm.type == "checkbox" && elm.checked) {
|
||||
if(typeof(myObj[name]) == 'undefined') {
|
||||
myObj[name]=[ ];
|
||||
}
|
||||
myObj[name].push(elm.value);
|
||||
} else if (elm.type == "select-multiple") {
|
||||
if(typeof(myObj[name]) == 'undefined') {
|
||||
myObj[name]=[ ];
|
||||
}
|
||||
for (var jdx=0,len3=elm.options.length; jdx<len3; ++jdx) {
|
||||
if (elm.options[jdx].selected) {
|
||||
myObj[name].push(elm.options[jdx].value);
|
||||
}
|
||||
}
|
||||
} // if
|
||||
name=undefined;
|
||||
}); // forEach
|
||||
***/
|
||||
return obj;
|
||||
},
|
||||
|
||||
isValid: function() {
|
||||
// TODO: ComboBox might need time to process a recently input value. This should be async?
|
||||
// make sure that every widget that has a validator function returns true
|
||||
return dojo.every(this.getDescendants(), function(widget){
|
||||
return !widget.isValid || widget.isValid();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.Form",
|
||||
[dijit._Widget, dijit._Templated, dijit.form._FormMixin],
|
||||
null
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,317 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.InlineEditBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.InlineEditBox"] = true;
|
||||
dojo.provide("dijit.form.InlineEditBox");
|
||||
|
||||
dojo.require("dojo.i18n");
|
||||
|
||||
dojo.require("dijit.form._FormWidget");
|
||||
dojo.require("dijit._Container");
|
||||
dojo.require("dijit.form.Button");
|
||||
|
||||
dojo.requireLocalization("dijit", "common", null, "ko,zh,ja,zh-tw,ru,it,hu,fr,pt,ROOT,pl,es,de,cs");
|
||||
|
||||
dojo.deprecated("dijit.form.InlineEditBox is deprecated, use dijit.InlineEditBox instead", "", "1.1");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.InlineEditBox",
|
||||
[dijit.form._FormWidget, dijit._Container],
|
||||
// summary
|
||||
// Wrapper widget to a text edit widget.
|
||||
// The text is displayed on the page using normal user-styling.
|
||||
// When clicked, the text is hidden, and the edit widget is
|
||||
// visible, allowing the text to be updated. Optionally,
|
||||
// Save and Cancel button are displayed below the edit widget.
|
||||
// When Save is clicked, the text is pulled from the edit
|
||||
// widget and redisplayed and the edit widget is again hidden.
|
||||
// Currently all textboxes that inherit from dijit.form.TextBox
|
||||
// are supported edit widgets.
|
||||
// An edit widget must support the following API to be used:
|
||||
// String getDisplayedValue() OR String getValue()
|
||||
// void setDisplayedValue(String) OR void setValue(String)
|
||||
// void focus()
|
||||
// It must also be able to initialize with style="display:none;" set.
|
||||
{
|
||||
templateString:"<span\n\t><fieldset dojoAttachPoint=\"editNode\" style=\"display:none;\" waiRole=\"presentation\"\n\t\t><div dojoAttachPoint=\"containerNode\" dojoAttachEvent=\"onkeypress:_onEditWidgetKeyPress\"></div\n\t\t><div dojoAttachPoint=\"buttonContainer\"\n\t\t\t><button class='saveButton' dojoAttachPoint=\"saveButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:save\">${buttonSave}</button\n\t\t\t><button class='cancelButton' dojoAttachPoint=\"cancelButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:cancel\">${buttonCancel}</button\n\t\t></div\n\t></fieldset\n\t><span tabIndex=\"0\" dojoAttachPoint=\"textNode,focusNode\" waiRole=\"button\" style=\"display:none;\"\n\t\tdojoAttachEvent=\"onkeypress:_onKeyPress,onclick:_onClick,onmouseout:_onMouseOut,onmouseover:_onMouseOver,onfocus:_onMouseOver,onblur:_onMouseOut\"\n\t></span\n></span>\n",
|
||||
|
||||
// editing: Boolean
|
||||
// Is the node currently in edit mode?
|
||||
editing: false,
|
||||
|
||||
// autoSave: Boolean
|
||||
// Changing the value automatically saves it, don't have to push save button
|
||||
autoSave: true,
|
||||
|
||||
// buttonSave: String
|
||||
// Save button label
|
||||
buttonSave: "",
|
||||
|
||||
// buttonCancel: String
|
||||
// Cancel button label
|
||||
buttonCancel: "",
|
||||
|
||||
// renderAsHtml: Boolean
|
||||
// should text render as HTML(true) or plain text(false)
|
||||
renderAsHtml: false,
|
||||
|
||||
widgetsInTemplate: true,
|
||||
|
||||
// _display: String
|
||||
// srcNodeRef display style
|
||||
_display:"",
|
||||
|
||||
startup: function(){
|
||||
// look for the input widget as a child of the containerNode
|
||||
if(!this._started){
|
||||
|
||||
if(this.editWidget){
|
||||
this.containerNode.appendChild(this.editWidget.domNode);
|
||||
}else{
|
||||
this.editWidget = this.getChildren()[0];
|
||||
}
|
||||
// #3209: copy the style from the source
|
||||
// don't copy ALL properties though, just the necessary/applicable ones
|
||||
var srcStyle=dojo.getComputedStyle(this.domNode);
|
||||
dojo.forEach(["fontWeight","fontFamily","fontSize","fontStyle"], function(prop){
|
||||
this.editWidget.focusNode.style[prop]=srcStyle[prop];
|
||||
}, this);
|
||||
this._setEditValue = dojo.hitch(this.editWidget,this.editWidget.setDisplayedValue||this.editWidget.setValue);
|
||||
this._getEditValue = dojo.hitch(this.editWidget,this.editWidget.getDisplayedValue||this.editWidget.getValue);
|
||||
this._setEditFocus = dojo.hitch(this.editWidget,this.editWidget.focus);
|
||||
this._isEditValid = dojo.hitch(this.editWidget,this.editWidget.isValid || function(){return true;});
|
||||
this.editWidget.onChange = dojo.hitch(this, "_onChange");
|
||||
|
||||
if(!this.autoSave){ // take over the setValue method so we can know when the value changes
|
||||
this._oldSetValue = this.editWidget.setValue;
|
||||
var _this = this;
|
||||
this.editWidget.setValue = dojo.hitch(this, function(value){
|
||||
_this._oldSetValue.apply(_this.editWidget, arguments);
|
||||
_this._onEditWidgetKeyPress(null); // check the Save button
|
||||
});
|
||||
}
|
||||
this._showText();
|
||||
|
||||
this._started = true;
|
||||
}
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
this._srcTag = this.srcNodeRef.tagName;
|
||||
this._srcStyle=dojo.getComputedStyle(this.srcNodeRef);
|
||||
// getComputedStyle is not good until after onLoad is called
|
||||
var srcNodeStyle = this.srcNodeRef.style;
|
||||
this._display="";
|
||||
if(srcNodeStyle && srcNodeStyle.display){ this._display=srcNodeStyle.display; }
|
||||
else{
|
||||
switch(this.srcNodeRef.tagName.toLowerCase()){
|
||||
case 'span':
|
||||
case 'input':
|
||||
case 'img':
|
||||
case 'button':
|
||||
this._display='inline';
|
||||
break;
|
||||
default:
|
||||
this._display='block';
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.inherited('postMixInProperties', arguments);
|
||||
this.messages = dojo.i18n.getLocalization("dijit", "common", this.lang);
|
||||
dojo.forEach(["buttonSave", "buttonCancel"], function(prop){
|
||||
if(!this[prop]){ this[prop] = this.messages[prop]; }
|
||||
}, this);
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
// don't call setValue yet since the editing widget is not setup
|
||||
if(this.autoSave){
|
||||
dojo.style(this.buttonContainer, "display", "none");
|
||||
}
|
||||
},
|
||||
|
||||
_onKeyPress: function(e){
|
||||
// summary: handle keypress when edit box is not open
|
||||
if(this.disabled || e.altKey || e.ctrlKey){ return; }
|
||||
if(e.charCode == dojo.keys.SPACE || e.keyCode == dojo.keys.ENTER){
|
||||
dojo.stopEvent(e);
|
||||
this._onClick(e);
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseOver: function(){
|
||||
if(!this.editing){
|
||||
var classname = this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion";
|
||||
dojo.addClass(this.textNode, classname);
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseOut: function(){
|
||||
if(!this.editing){
|
||||
var classStr = this.disabled ? "dijitDisabledClickableRegion" : "dijitClickableRegion";
|
||||
dojo.removeClass(this.textNode, classStr);
|
||||
}
|
||||
},
|
||||
|
||||
_onClick: function(e){
|
||||
// summary
|
||||
// When user clicks the text, then start editing.
|
||||
// Hide the text and display the form instead.
|
||||
|
||||
if(this.editing || this.disabled){ return; }
|
||||
this._onMouseOut();
|
||||
this.editing = true;
|
||||
|
||||
// show the edit form and hide the read only version of the text
|
||||
this._setEditValue(this._isEmpty ? '' : (this.renderAsHtml ? this.textNode.innerHTML : this.textNode.innerHTML.replace(/\s*\r?\n\s*/g,"").replace(/<br\/?>/gi, "\n").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&")));
|
||||
this._initialText = this._getEditValue();
|
||||
this._visualize();
|
||||
// Before changing the focus, give the browser time to render.
|
||||
setTimeout(dojo.hitch(this, function(){
|
||||
this._setEditFocus();
|
||||
this.saveButton.setDisabled(true);
|
||||
}), 1);
|
||||
},
|
||||
|
||||
_visualize: function(){
|
||||
dojo.style(this.editNode, "display", this.editing ? this._display : "none");
|
||||
// #3749: try to set focus now to fix missing caret
|
||||
// #3997: call right after this.containerNode appears
|
||||
if(this.editing){this._setEditFocus();}
|
||||
dojo.style(this.textNode, "display", this.editing ? "none" : this._display);
|
||||
},
|
||||
|
||||
_showText: function(){
|
||||
var value = "" + this._getEditValue(); // "" is to make sure its a string
|
||||
dijit.form.InlineEditBox.superclass.setValue.call(this, value);
|
||||
// whitespace is really hard to click so show a ?
|
||||
// TODO: show user defined message in gray
|
||||
if(/^\s*$/.test(value)){ value = "?"; this._isEmpty = true; }
|
||||
else { this._isEmpty = false; }
|
||||
if(this.renderAsHtml){
|
||||
this.textNode.innerHTML = value;
|
||||
}else{
|
||||
this.textNode.innerHTML = "";
|
||||
if(value.split){
|
||||
var _this=this;
|
||||
var isFirst = true;
|
||||
dojo.forEach(value.split("\n"), function(line){
|
||||
if(isFirst){
|
||||
isFirst = false;
|
||||
}else{
|
||||
_this.textNode.appendChild(document.createElement("BR")); // preserve line breaks
|
||||
}
|
||||
_this.textNode.appendChild(document.createTextNode(line)); // use text nodes so that imbedded tags can be edited
|
||||
});
|
||||
}else{
|
||||
this.textNode.appendChild(document.createTextNode(value));
|
||||
}
|
||||
}
|
||||
this._visualize();
|
||||
},
|
||||
|
||||
save: function(e){
|
||||
// summary: Callback when user presses "Save" button or it's simulated.
|
||||
// e is passed in if click on save button or user presses Enter. It's not
|
||||
// passed in when called by _onBlur.
|
||||
if(typeof e == "object"){ dojo.stopEvent(e); }
|
||||
if(!this.enableSave()){ return; }
|
||||
this.editing = false;
|
||||
this._showText();
|
||||
// If save button pressed on non-autoSave widget or Enter pressed on autoSave
|
||||
// widget, restore focus to the inline text.
|
||||
if(e){ dijit.focus(this.focusNode); }
|
||||
|
||||
if(this._lastValue != this._lastValueReported){
|
||||
this.onChange(this._lastValue); // tell the world that we have changed
|
||||
}
|
||||
},
|
||||
|
||||
cancel: function(e){
|
||||
// summary: Callback when user presses "Cancel" button or it's simulated.
|
||||
// e is passed in if click on cancel button or user presses Esc. It's not
|
||||
// passed in when called by _onBlur.
|
||||
if(e){ dojo.stopEvent(e); }
|
||||
this.editing = false;
|
||||
this._visualize();
|
||||
// If cancel button pressed on non-autoSave widget or Esc pressed on autoSave
|
||||
// widget, restore focus to the inline text.
|
||||
if(e){ dijit.focus(this.focusNode); }
|
||||
},
|
||||
|
||||
setValue: function(/*String*/ value){
|
||||
// sets the text without informing the server
|
||||
this._setEditValue(value);
|
||||
this.editing = false;
|
||||
this._showText();
|
||||
},
|
||||
|
||||
_onEditWidgetKeyPress: function(e){
|
||||
// summary:
|
||||
// Callback when keypress in the edit box (see template).
|
||||
// For autoSave widgets, if Esc/Enter, call cancel/save.
|
||||
// For non-autoSave widgets, enable save button if the text value is
|
||||
// different than the original value.
|
||||
if(!this.editing){ return; }
|
||||
if(this.autoSave){
|
||||
// If Enter/Esc pressed, treat as save/cancel.
|
||||
if(e.keyCode == dojo.keys.ESCAPE){
|
||||
this.cancel(e);
|
||||
}else if(e.keyCode == dojo.keys.ENTER){
|
||||
this.save(e);
|
||||
}
|
||||
}else{
|
||||
var _this = this;
|
||||
// Delay before calling _getEditValue.
|
||||
// The delay gives the browser a chance to update the textarea.
|
||||
setTimeout(
|
||||
function(){
|
||||
_this.saveButton.setDisabled(_this._getEditValue() == _this._initialText);
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
// summary:
|
||||
// Called by the focus manager in focus.js when focus moves outside of the
|
||||
// InlineEditBox widget (or it's descendants).
|
||||
if(this.autoSave && this.editing){
|
||||
if(this._getEditValue() == this._initialText){
|
||||
this.cancel();
|
||||
}else{
|
||||
this.save();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
enableSave: function(){
|
||||
// summary: User replacable function returning a Boolean to indicate
|
||||
// if the Save button should be enabled or not - usually due to invalid conditions
|
||||
return this._isEditValid();
|
||||
},
|
||||
|
||||
_onChange: function(){
|
||||
// summary:
|
||||
// This is called when the underlying widget fires an onChange event,
|
||||
// which means that the user has finished entering the value
|
||||
if(!this.editing){
|
||||
this._showText(); // asynchronous update made famous by ComboBox/FilteringSelect
|
||||
}else if(this.autoSave){
|
||||
this.save(1);
|
||||
}else{
|
||||
// #3752
|
||||
// if the keypress does not bubble up to the div, (iframe in TextArea blocks it for example)
|
||||
// make sure the save button gets enabled
|
||||
this.saveButton.setDisabled((this._getEditValue() == this._initialText) || !this.enabledSave());
|
||||
}
|
||||
},
|
||||
|
||||
setDisabled: function(/*Boolean*/ disabled){
|
||||
this.saveButton.setDisabled(disabled);
|
||||
this.cancelButton.setDisabled(disabled);
|
||||
this.textNode.disabled = disabled;
|
||||
this.editWidget.setDisabled(disabled);
|
||||
this.inherited('setDisabled', arguments);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.NumberSpinner"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.NumberSpinner"] = true;
|
||||
dojo.provide("dijit.form.NumberSpinner");
|
||||
|
||||
dojo.require("dijit.form._Spinner");
|
||||
dojo.require("dijit.form.NumberTextBox");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.NumberSpinner",
|
||||
[dijit.form._Spinner, dijit.form.NumberTextBoxMixin],
|
||||
{
|
||||
// summary: Number Spinner
|
||||
// description: This widget is the same as NumberTextBox but with up/down arrows added
|
||||
|
||||
required: true,
|
||||
|
||||
adjust: function(/* Object */ val, /*Number*/ delta){
|
||||
// summary: change Number val by the given amount
|
||||
var newval = val+delta;
|
||||
if(isNaN(val) || isNaN(newval)){ return val; }
|
||||
if((typeof this.constraints.max == "number") && (newval > this.constraints.max)){
|
||||
newval = this.constraints.max;
|
||||
}
|
||||
if((typeof this.constraints.min == "number") && (newval < this.constraints.min)){
|
||||
newval = this.constraints.min;
|
||||
}
|
||||
return newval;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.NumberTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.NumberTextBox"] = true;
|
||||
dojo.provide("dijit.form.NumberTextBox");
|
||||
|
||||
dojo.require("dijit.form.ValidationTextBox");
|
||||
dojo.require("dojo.number");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.NumberTextBoxMixin",
|
||||
null,
|
||||
{
|
||||
// summary:
|
||||
// A mixin for all number textboxes
|
||||
regExpGen: dojo.number.regexp,
|
||||
|
||||
format: function(/*Number*/ value, /*Object*/ constraints){
|
||||
if(isNaN(value)){ return ""; }
|
||||
return dojo.number.format(value, constraints);
|
||||
},
|
||||
|
||||
parse: dojo.number.parse,
|
||||
|
||||
filter: function(/*Number*/ value){
|
||||
if(typeof value == "string"){ return this.inherited('filter', arguments); }
|
||||
return (isNaN(value) ? '' : value);
|
||||
},
|
||||
|
||||
value: NaN
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.NumberTextBox",
|
||||
[dijit.form.RangeBoundTextBox,dijit.form.NumberTextBoxMixin],
|
||||
{
|
||||
// summary:
|
||||
// A validating, serializable, range-bound text box.
|
||||
// constraints object: min, max, places
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,401 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.Slider"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.Slider"] = true;
|
||||
dojo.provide("dijit.form.Slider");
|
||||
|
||||
dojo.require("dijit.form._FormWidget");
|
||||
dojo.require("dijit._Container");
|
||||
dojo.require("dojo.dnd.move");
|
||||
dojo.require("dijit.form.Button");
|
||||
dojo.require("dojo.number");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.HorizontalSlider",
|
||||
[dijit.form._FormWidget, dijit._Container],
|
||||
{
|
||||
// summary
|
||||
// A form widget that allows one to select a value with a horizontally draggable image
|
||||
|
||||
templateString:"<table class=\"dijit dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"containerNode,topDecoration\" class=\"dijitReset\" style=\"text-align:center;width:100%;\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitHorizontalSliderButtonContainer\"\n\t\t\t><div class=\"dijitHorizontalSliderDecrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"decrementButton\" dojoAttachEvent=\"onclick: decrement\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitHorizontalSliderBumper dijitSliderLeftBumper dijitHorizontalSliderLeftBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><input dojoAttachPoint=\"valueNode\" type=\"hidden\" name=\"${name}\"\n\t\t\t/><div style=\"position:relative;\" dojoAttachPoint=\"sliderBarContainer\"\n\t\t\t\t><div dojoAttachPoint=\"progressBar\" class=\"dijitSliderBar dijitHorizontalSliderBar dijitSliderProgressBar dijitHorizontalSliderProgressBar\" dojoAttachEvent=\"onclick:_onBarClick\"\n\t\t\t\t\t><div dojoAttachPoint=\"sliderHandle,focusNode\" class=\"dijitSliderMoveable dijitHorizontalSliderMoveable\" dojoAttachEvent=\"onkeypress:_onKeyPress,onclick:_onHandleClick\" waiRole=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"\n\t\t\t\t\t\t><div class=\"dijitSliderImageHandle dijitHorizontalSliderImageHandle\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t\t><div dojoAttachPoint=\"remainingBar\" class=\"dijitSliderBar dijitHorizontalSliderBar dijitSliderRemainingBar dijitHorizontalSliderRemainingBar\" dojoAttachEvent=\"onclick:_onBarClick\"></div\n\t\t\t></div\n\t\t></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><div class=\"dijitSliderBar dijitSliderBumper dijitHorizontalSliderBumper dijitSliderRightBumper dijitHorizontalSliderRightBumper\"></div\n\t\t></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitHorizontalSliderButtonContainer\" style=\"right:0px;\"\n\t\t\t><div class=\"dijitHorizontalSliderIncrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"incrementButton\" dojoAttachEvent=\"onclick: increment\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t\t><td dojoAttachPoint=\"containerNode,bottomDecoration\" class=\"dijitReset\" style=\"text-align:center;\"></td\n\t\t><td class=\"dijitReset\" colspan=\"2\"></td\n\t></tr\n></table>\n",
|
||||
value: 0,
|
||||
|
||||
// showButtons: boolean
|
||||
// Show increment/decrement buttons at the ends of the slider?
|
||||
showButtons: true,
|
||||
|
||||
// minimum:: integer
|
||||
// The minimum value allowed.
|
||||
minimum: 0,
|
||||
|
||||
// maximum: integer
|
||||
// The maximum allowed value.
|
||||
maximum: 100,
|
||||
|
||||
// discreteValues: integer
|
||||
// The maximum allowed values dispersed evenly between minimum and maximum (inclusive).
|
||||
discreteValues: Infinity,
|
||||
|
||||
// pageIncrement: integer
|
||||
// The amount of change with shift+arrow
|
||||
pageIncrement: 2,
|
||||
|
||||
// clickSelect: boolean
|
||||
// If clicking the progress bar changes the value or not
|
||||
clickSelect: true,
|
||||
|
||||
widgetsInTemplate: true,
|
||||
|
||||
attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
|
||||
{id:"", name:"valueNode"}),
|
||||
|
||||
baseClass: "dijitSlider",
|
||||
|
||||
_mousePixelCoord: "pageX",
|
||||
_pixelCount: "w",
|
||||
_startingPixelCoord: "x",
|
||||
_startingPixelCount: "l",
|
||||
_handleOffsetCoord: "left",
|
||||
_progressPixelSize: "width",
|
||||
_upsideDown: false,
|
||||
|
||||
_onKeyPress: function(/*Event*/ e){
|
||||
if(this.disabled || e.altKey || e.ctrlKey){ return; }
|
||||
switch(e.keyCode){
|
||||
case dojo.keys.HOME:
|
||||
this.setValue(this.minimum);
|
||||
break;
|
||||
case dojo.keys.END:
|
||||
this.setValue(this.maximum);
|
||||
break;
|
||||
case dojo.keys.UP_ARROW:
|
||||
case (this._isReversed() ? dojo.keys.LEFT_ARROW : dojo.keys.RIGHT_ARROW):
|
||||
case dojo.keys.PAGE_UP:
|
||||
this.increment(e);
|
||||
break;
|
||||
case dojo.keys.DOWN_ARROW:
|
||||
case (this._isReversed() ? dojo.keys.RIGHT_ARROW : dojo.keys.LEFT_ARROW):
|
||||
case dojo.keys.PAGE_DOWN:
|
||||
this.decrement(e);
|
||||
break;
|
||||
default:
|
||||
this.inherited("_onKeyPress", arguments);
|
||||
return;
|
||||
}
|
||||
dojo.stopEvent(e);
|
||||
},
|
||||
|
||||
_onHandleClick: function(e){
|
||||
if(this.disabled){ return; }
|
||||
if(!dojo.isIE){
|
||||
// make sure you get focus when dragging the handle
|
||||
// (but don't do on IE because it causes a flicker on mouse up (due to blur then focus)
|
||||
dijit.focus(this.sliderHandle);
|
||||
}
|
||||
dojo.stopEvent(e);
|
||||
},
|
||||
|
||||
_isReversed: function() {
|
||||
return !(this._upsideDown || this.isLeftToRight());
|
||||
},
|
||||
|
||||
_onBarClick: function(e){
|
||||
if(this.disabled || !this.clickSelect){ return; }
|
||||
dijit.focus(this.sliderHandle);
|
||||
dojo.stopEvent(e);
|
||||
var abspos = dojo.coords(this.sliderBarContainer, true);
|
||||
var pixelValue = e[this._mousePixelCoord] - abspos[this._startingPixelCoord];
|
||||
this._setPixelValue(this._isReversed() || this._upsideDown ? (abspos[this._pixelCount] - pixelValue) : pixelValue, abspos[this._pixelCount], true);
|
||||
},
|
||||
|
||||
_setPixelValue: function(/*Number*/ pixelValue, /*Number*/ maxPixels, /*Boolean, optional*/ priorityChange){
|
||||
if(this.disabled){ return; }
|
||||
pixelValue = pixelValue < 0 ? 0 : maxPixels < pixelValue ? maxPixels : pixelValue;
|
||||
var count = this.discreteValues;
|
||||
if(count <= 1 || count == Infinity){ count = maxPixels; }
|
||||
count--;
|
||||
var pixelsPerValue = maxPixels / count;
|
||||
var wholeIncrements = Math.round(pixelValue / pixelsPerValue);
|
||||
this.setValue((this.maximum-this.minimum)*wholeIncrements/count + this.minimum, priorityChange);
|
||||
},
|
||||
|
||||
setValue: function(/*Number*/ value, /*Boolean, optional*/ priorityChange){
|
||||
this.valueNode.value = this.value = value;
|
||||
this.inherited('setValue', arguments);
|
||||
var percent = (value - this.minimum) / (this.maximum - this.minimum);
|
||||
this.progressBar.style[this._progressPixelSize] = (percent*100) + "%";
|
||||
this.remainingBar.style[this._progressPixelSize] = ((1-percent)*100) + "%";
|
||||
},
|
||||
|
||||
_bumpValue: function(signedChange){
|
||||
if(this.disabled){ return; }
|
||||
var s = dojo.getComputedStyle(this.sliderBarContainer);
|
||||
var c = dojo._getContentBox(this.sliderBarContainer, s);
|
||||
var count = this.discreteValues;
|
||||
if(count <= 1 || count == Infinity){ count = c[this._pixelCount]; }
|
||||
count--;
|
||||
var value = (this.value - this.minimum) * count / (this.maximum - this.minimum) + signedChange;
|
||||
if(value < 0){ value = 0; }
|
||||
if(value > count){ value = count; }
|
||||
value = value * (this.maximum - this.minimum) / count + this.minimum;
|
||||
this.setValue(value, true);
|
||||
},
|
||||
|
||||
decrement: function(e){
|
||||
// summary
|
||||
// decrement slider by 1 unit
|
||||
this._bumpValue(e.keyCode == dojo.keys.PAGE_DOWN?-this.pageIncrement:-1);
|
||||
},
|
||||
|
||||
increment: function(e){
|
||||
// summary
|
||||
// increment slider by 1 unit
|
||||
this._bumpValue(e.keyCode == dojo.keys.PAGE_UP?this.pageIncrement:1);
|
||||
},
|
||||
|
||||
_mouseWheeled: function(/*Event*/ evt){
|
||||
dojo.stopEvent(evt);
|
||||
var scrollAmount = 0;
|
||||
if(typeof evt.wheelDelta == 'number'){ // IE
|
||||
scrollAmount = evt.wheelDelta;
|
||||
}else if(typeof evt.detail == 'number'){ // Mozilla+Firefox
|
||||
scrollAmount = -evt.detail;
|
||||
}
|
||||
if(scrollAmount > 0){
|
||||
this.increment(evt);
|
||||
}else if(scrollAmount < 0){
|
||||
this.decrement(evt);
|
||||
}
|
||||
},
|
||||
|
||||
startup: function(){
|
||||
dojo.forEach(this.getChildren(), function(child){
|
||||
if(this[child.container] != this.containerNode){
|
||||
this[child.container].appendChild(child.domNode);
|
||||
}
|
||||
}, this);
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
dijit.form.HorizontalSlider.superclass.setValue.call(this, this.value, true);
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
if(this.showButtons){
|
||||
this.incrementButton.style.display="";
|
||||
this.decrementButton.style.display="";
|
||||
}
|
||||
this.connect(this.domNode, dojo.isIE ? "onmousewheel" : 'DOMMouseScroll', "_mouseWheeled");
|
||||
|
||||
// define a custom constructor for a SliderMover that points back to me
|
||||
var _self = this;
|
||||
var mover = function(){
|
||||
dijit.form._SliderMover.apply(this, arguments);
|
||||
this.widget = _self;
|
||||
};
|
||||
dojo.extend(mover, dijit.form._SliderMover.prototype);
|
||||
|
||||
this._movable = new dojo.dnd.Moveable(this.sliderHandle, {mover: mover});
|
||||
this.inherited('postCreate', arguments);
|
||||
},
|
||||
|
||||
destroy: function(){
|
||||
this._movable.destroy();
|
||||
this.inherited('destroy', arguments);
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.VerticalSlider",
|
||||
dijit.form.HorizontalSlider,
|
||||
{
|
||||
// summary
|
||||
// A form widget that allows one to select a value with a vertically draggable image
|
||||
|
||||
templateString:"<table class=\"dijitReset dijitSlider\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" rules=\"none\"\n><tbody class=\"dijitReset\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitVerticalSliderButtonContainer\"\n\t\t\t><div class=\"dijitVerticalSliderIncrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"incrementButton\" dojoAttachEvent=\"onclick: increment\"><span class=\"dijitSliderButtonInner\">+</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><center><div class=\"dijitSliderBar dijitSliderBumper dijitVerticalSliderBumper dijitSliderTopBumper dijitVerticalSliderTopBumper\"></div></center\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td dojoAttachPoint=\"leftDecoration\" class=\"dijitReset\" style=\"text-align:center;height:100%;\"></td\n\t\t><td class=\"dijitReset\" style=\"height:100%;\"\n\t\t\t><input dojoAttachPoint=\"valueNode\" type=\"hidden\" name=\"${name}\"\n\t\t\t/><center style=\"position:relative;height:100%;\" dojoAttachPoint=\"sliderBarContainer\"\n\t\t\t\t><div dojoAttachPoint=\"remainingBar\" class=\"dijitSliderBar dijitVerticalSliderBar dijitSliderRemainingBar dijitVerticalSliderRemainingBar\" dojoAttachEvent=\"onclick:_onBarClick\"></div\n\t\t\t\t><div dojoAttachPoint=\"progressBar\" class=\"dijitSliderBar dijitVerticalSliderBar dijitSliderProgressBar dijitVerticalSliderProgressBar\" dojoAttachEvent=\"onclick:_onBarClick\"\n\t\t\t\t\t><div dojoAttachPoint=\"sliderHandle,focusNode\" class=\"dijitSliderMoveable\" dojoAttachEvent=\"onkeypress:_onKeyPress,onclick:_onHandleClick\" style=\"vertical-align:top;\" waiRole=\"slider\" valuemin=\"${minimum}\" valuemax=\"${maximum}\"\n\t\t\t\t\t\t><div class=\"dijitSliderImageHandle dijitVerticalSliderImageHandle\"></div\n\t\t\t\t\t></div\n\t\t\t\t></div\n\t\t\t></center\n\t\t></td\n\t\t><td dojoAttachPoint=\"containerNode,rightDecoration\" class=\"dijitReset\" style=\"text-align:center;height:100%;\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset\"\n\t\t\t><center><div class=\"dijitSliderBar dijitSliderBumper dijitVerticalSliderBumper dijitSliderBottomBumper dijitVerticalSliderBottomBumper\"></div></center\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset\"></td\n\t\t><td class=\"dijitReset dijitSliderButtonContainer dijitVerticalSliderButtonContainer\"\n\t\t\t><div class=\"dijitVerticalSliderDecrementIcon\" tabIndex=\"-1\" style=\"display:none\" dojoAttachPoint=\"decrementButton\" dojoAttachEvent=\"onclick: decrement\"><span class=\"dijitSliderButtonInner\">-</span></div\n\t\t></td\n\t\t><td class=\"dijitReset\"></td\n\t></tr\n></tbody></table>\n",
|
||||
_mousePixelCoord: "pageY",
|
||||
_pixelCount: "h",
|
||||
_startingPixelCoord: "y",
|
||||
_startingPixelCount: "t",
|
||||
_handleOffsetCoord: "top",
|
||||
_progressPixelSize: "height",
|
||||
_upsideDown: true
|
||||
});
|
||||
|
||||
dojo.declare("dijit.form._SliderMover",
|
||||
dojo.dnd.Mover,
|
||||
{
|
||||
onMouseMove: function(e){
|
||||
var widget = this.widget;
|
||||
var c = this.constraintBox;
|
||||
if(!c){
|
||||
var container = widget.sliderBarContainer;
|
||||
var s = dojo.getComputedStyle(container);
|
||||
var c = dojo._getContentBox(container, s);
|
||||
c[widget._startingPixelCount] = 0;
|
||||
this.constraintBox = c;
|
||||
}
|
||||
var m = this.marginBox;
|
||||
var pixelValue = widget._isReversed() ?
|
||||
e[widget._mousePixelCoord] - dojo._abs(widget.sliderBarContainer).x :
|
||||
m[widget._startingPixelCount] + e[widget._mousePixelCoord];
|
||||
dojo.hitch(widget, "_setPixelValue")(widget._isReversed() || widget._upsideDown? (c[widget._pixelCount]-pixelValue) : pixelValue, c[widget._pixelCount]);
|
||||
},
|
||||
|
||||
destroy: function(e){
|
||||
var widget = this.widget;
|
||||
widget.setValue(widget.value, true);
|
||||
dojo.dnd.Mover.prototype.destroy.call(this);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
dojo.declare("dijit.form.HorizontalRule", [dijit._Widget, dijit._Templated],
|
||||
{
|
||||
// Summary:
|
||||
// Create hash marks for the Horizontal slider
|
||||
templateString: '<div class="RuleContainer HorizontalRuleContainer"></div>',
|
||||
|
||||
// count: Integer
|
||||
// Number of hash marks to generate
|
||||
count: 3,
|
||||
|
||||
// container: Node
|
||||
// If this is a child widget, connect it to this parent node
|
||||
container: "containerNode",
|
||||
|
||||
// ruleStyle: String
|
||||
// CSS style to apply to individual hash marks
|
||||
ruleStyle: "",
|
||||
|
||||
_positionPrefix: '<div class="RuleMark HorizontalRuleMark" style="left:',
|
||||
_positionSuffix: '%;',
|
||||
_suffix: '"></div>',
|
||||
|
||||
_genHTML: function(pos, ndx){
|
||||
return this._positionPrefix + pos + this._positionSuffix + this.ruleStyle + this._suffix;
|
||||
},
|
||||
|
||||
_isHorizontal: true,
|
||||
|
||||
postCreate: function(){
|
||||
if(this.count==1){
|
||||
var innerHTML = this._genHTML(50, 0);
|
||||
}else{
|
||||
var interval = 100 / (this.count-1);
|
||||
if(!this._isHorizontal || this.isLeftToRight()){
|
||||
var innerHTML = this._genHTML(0, 0);
|
||||
for(var i=1; i < this.count-1; i++){
|
||||
innerHTML += this._genHTML(interval*i, i);
|
||||
}
|
||||
innerHTML += this._genHTML(100, this.count-1);
|
||||
}else{
|
||||
var innerHTML = this._genHTML(100, 0);
|
||||
for(var i=1; i < this.count-1; i++){
|
||||
innerHTML += this._genHTML(100-interval*i, i);
|
||||
}
|
||||
innerHTML += this._genHTML(0, this.count-1);
|
||||
}
|
||||
}
|
||||
this.domNode.innerHTML = innerHTML;
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare("dijit.form.VerticalRule", dijit.form.HorizontalRule,
|
||||
{
|
||||
// Summary:
|
||||
// Create hash marks for the Vertical slider
|
||||
templateString: '<div class="RuleContainer VerticalRuleContainer"></div>',
|
||||
_positionPrefix: '<div class="RuleMark VerticalRuleMark" style="top:',
|
||||
|
||||
_isHorizontal: false
|
||||
});
|
||||
|
||||
dojo.declare("dijit.form.HorizontalRuleLabels", dijit.form.HorizontalRule,
|
||||
{
|
||||
// Summary:
|
||||
// Create labels for the Horizontal slider
|
||||
templateString: '<div class="RuleContainer HorizontalRuleContainer"></div>',
|
||||
|
||||
// labelStyle: String
|
||||
// CSS style to apply to individual text labels
|
||||
labelStyle: "",
|
||||
|
||||
// labels: Array
|
||||
// Array of text labels to render - evenly spaced from left-to-right or bottom-to-top
|
||||
labels: [],
|
||||
|
||||
// numericMargin: Integer
|
||||
// Number of generated numeric labels that should be rendered as '' on the ends when labels[] are not specified
|
||||
numericMargin: 0,
|
||||
|
||||
// numericMinimum: Integer
|
||||
// Leftmost label value for generated numeric labels when labels[] are not specified
|
||||
minimum: 0,
|
||||
|
||||
// numericMaximum: Integer
|
||||
// Rightmost label value for generated numeric labels when labels[] are not specified
|
||||
maximum: 1,
|
||||
|
||||
// constraints: object
|
||||
// pattern, places, lang, et al (see dojo.number) for generated numeric labels when labels[] are not specified
|
||||
constraints: {pattern:"#%"},
|
||||
|
||||
_positionPrefix: '<div class="RuleLabelContainer HorizontalRuleLabelContainer" style="left:',
|
||||
_labelPrefix: '"><span class="RuleLabel HorizontalRuleLabel">',
|
||||
_suffix: '</span></div>',
|
||||
|
||||
_calcPosition: function(pos){
|
||||
return pos;
|
||||
},
|
||||
|
||||
_genHTML: function(pos, ndx){
|
||||
return this._positionPrefix + this._calcPosition(pos) + this._positionSuffix + this.labelStyle + this._labelPrefix + this.labels[ndx] + this._suffix;
|
||||
},
|
||||
|
||||
getLabels: function(){
|
||||
// summary: user replaceable function to return the labels array
|
||||
|
||||
// if the labels array was not specified directly, then see if <li> children were
|
||||
var labels = this.labels;
|
||||
if(!labels.length){
|
||||
// for markup creation, labels are specified as child elements
|
||||
labels = dojo.query("> li", this.srcNodeRef).map(function(node){
|
||||
return String(node.innerHTML);
|
||||
});
|
||||
}
|
||||
this.srcNodeRef.innerHTML = '';
|
||||
// if the labels were not specified directly and not as <li> children, then calculate numeric labels
|
||||
if(!labels.length && this.count > 1){
|
||||
var start = this.minimum;
|
||||
var inc = (this.maximum - start) / (this.count-1);
|
||||
for (var i=0; i < this.count; i++){
|
||||
labels.push((i<this.numericMargin||i>=(this.count-this.numericMargin))? '' : dojo.number.format(start, this.constraints));
|
||||
start += inc;
|
||||
}
|
||||
}
|
||||
return labels;
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.inherited('postMixInProperties', arguments);
|
||||
this.labels = this.getLabels();
|
||||
this.count = this.labels.length;
|
||||
}
|
||||
});
|
||||
|
||||
dojo.declare("dijit.form.VerticalRuleLabels", dijit.form.HorizontalRuleLabels,
|
||||
{
|
||||
// Summary:
|
||||
// Create labels for the Vertical slider
|
||||
templateString: '<div class="RuleContainer VerticalRuleContainer"></div>',
|
||||
|
||||
_positionPrefix: '<div class="RuleLabelContainer VerticalRuleLabelContainer" style="top:',
|
||||
_labelPrefix: '"><span class="RuleLabel VerticalRuleLabel">',
|
||||
|
||||
_calcPosition: function(pos){
|
||||
return 100-pos;
|
||||
},
|
||||
|
||||
_isHorizontal: false
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.TextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.TextBox"] = true;
|
||||
dojo.provide("dijit.form.TextBox");
|
||||
|
||||
dojo.require("dijit.form._FormWidget");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.TextBox",
|
||||
dijit.form._FormWidget,
|
||||
{
|
||||
// summary:
|
||||
// A generic textbox field.
|
||||
// Serves as a base class to derive more specialized functionality in subclasses.
|
||||
|
||||
// trim: Boolean
|
||||
// Removes leading and trailing whitespace if true. Default is false.
|
||||
trim: false,
|
||||
|
||||
// uppercase: Boolean
|
||||
// Converts all characters to uppercase if true. Default is false.
|
||||
uppercase: false,
|
||||
|
||||
// lowercase: Boolean
|
||||
// Converts all characters to lowercase if true. Default is false.
|
||||
lowercase: false,
|
||||
|
||||
// propercase: Boolean
|
||||
// Converts the first character of each word to uppercase if true.
|
||||
propercase: false,
|
||||
|
||||
// maxLength: String
|
||||
// HTML INPUT tag maxLength declaration.
|
||||
maxLength: "",
|
||||
|
||||
templateString:"<input class=\"dojoTextBox\" dojoAttachPoint='textbox,focusNode' name=\"${name}\"\n\tdojoAttachEvent='onmouseenter:_onMouse,onmouseleave:_onMouse,onfocus:_onMouse,onblur:_onMouse,onkeyup,onkeypress:_onKeyPress'\n\tautocomplete=\"off\" type=\"${type}\"\n\t/>\n",
|
||||
baseClass: "dijitTextBox",
|
||||
|
||||
attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
|
||||
{maxLength:"focusNode"}),
|
||||
|
||||
getDisplayedValue: function(){
|
||||
return this.filter(this.textbox.value);
|
||||
},
|
||||
|
||||
getValue: function(){
|
||||
return this.parse(this.getDisplayedValue(), this.constraints);
|
||||
},
|
||||
|
||||
setValue: function(value, /*Boolean, optional*/ priorityChange, /*String, optional*/ formattedValue){
|
||||
var filteredValue = this.filter(value);
|
||||
if((typeof filteredValue == typeof value) && (formattedValue == null || formattedValue == undefined)){
|
||||
formattedValue = this.format(filteredValue, this.constraints);
|
||||
}
|
||||
if(formattedValue != null && formattedValue != undefined){
|
||||
this.textbox.value = formattedValue;
|
||||
}
|
||||
dijit.form.TextBox.superclass.setValue.call(this, filteredValue, priorityChange);
|
||||
},
|
||||
|
||||
setDisplayedValue: function(/*String*/value){
|
||||
this.textbox.value = value;
|
||||
this.setValue(this.getValue(), true);
|
||||
},
|
||||
|
||||
forWaiValuenow: function(){
|
||||
return this.getDisplayedValue();
|
||||
},
|
||||
|
||||
format: function(/* String */ value, /* Object */ constraints){
|
||||
// summary: Replacable function to convert a value to a properly formatted string
|
||||
return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));
|
||||
},
|
||||
|
||||
parse: function(/* String */ value, /* Object */ constraints){
|
||||
// summary: Replacable function to convert a formatted string to a value
|
||||
return value;
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
// setting the value here is needed since value="" in the template causes "undefined"
|
||||
// and setting in the DOM (instead of the JS object) helps with form reset actions
|
||||
this.textbox.setAttribute("value", this.getDisplayedValue());
|
||||
this.inherited('postCreate', arguments);
|
||||
|
||||
if(this.srcNodeRef){
|
||||
dojo.style(this.textbox, "cssText", this.style);
|
||||
this.textbox.className += " " + this["class"];
|
||||
}
|
||||
this._layoutHack();
|
||||
},
|
||||
|
||||
_layoutHack: function(){
|
||||
// summary: work around table sizing bugs on FF2 by forcing redraw
|
||||
if(dojo.isFF == 2 && this.domNode.tagName=="TABLE"){
|
||||
var node=this.domNode, _this = this;
|
||||
setTimeout(function(){
|
||||
var oldWidth = node.style.width;
|
||||
node.style.width = "0";
|
||||
setTimeout(function(){
|
||||
node.style.width = oldWidth;
|
||||
}, 0);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
|
||||
filter: function(val){
|
||||
// summary: Apply various filters to textbox value
|
||||
if(val == undefined || val == null){ return ""; }
|
||||
else if(typeof val != "string"){ return val; }
|
||||
if(this.trim){
|
||||
val = dojo.trim(val);
|
||||
}
|
||||
if(this.uppercase){
|
||||
val = val.toUpperCase();
|
||||
}
|
||||
if(this.lowercase){
|
||||
val = val.toLowerCase();
|
||||
}
|
||||
if(this.propercase){
|
||||
val = val.replace(/[^\s]+/g, function(word){
|
||||
return word.substring(0,1).toUpperCase() + word.substring(1);
|
||||
});
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
||||
// event handlers, you can over-ride these in your own subclasses
|
||||
_onBlur: function(){
|
||||
this.setValue(this.getValue(), (this.isValid ? this.isValid() : true));
|
||||
},
|
||||
|
||||
onkeyup: function(){
|
||||
// TODO: it would be nice to massage the value (ie: automatic uppercase, etc) as the user types
|
||||
// but this messes up the cursor position if you are typing into the middle of a word, and
|
||||
// also trimming doesn't work correctly (it prevents spaces between words too!)
|
||||
// this.setValue(this.getValue());
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.Textarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.Textarea"] = true;
|
||||
dojo.provide("dijit.form.Textarea");
|
||||
|
||||
dojo.require("dijit.form._FormWidget");
|
||||
dojo.require("dojo.i18n");
|
||||
dojo.requireLocalization("dijit", "Textarea", null, "ROOT");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.Textarea",
|
||||
dijit.form._FormWidget,
|
||||
{
|
||||
// summary
|
||||
// A textarea that resizes vertically to contain the data.
|
||||
// Takes nearly all the parameters (name, value, etc.) that a vanilla textarea takes.
|
||||
// Cols is not supported and the width should be specified with style width.
|
||||
// Rows is not supported since this widget adjusts the height.
|
||||
// usage:
|
||||
// <textarea dojoType="dijit.form.TextArea">...</textarea>
|
||||
|
||||
attributeMap: dojo.mixin(dojo.clone(dijit.form._FormWidget.prototype.attributeMap),
|
||||
{style:"styleNode", 'class':"styleNode"}),
|
||||
|
||||
templateString: (dojo.isIE || dojo.isSafari || dojo.isMozilla) ?
|
||||
((dojo.isIE || dojo.isSafari) ? '<fieldset id="${id}" class="dijitInline dijitInputField dijitTextArea" dojoAttachPoint="styleNode" waiRole="presentation"><div dojoAttachPoint="editNode,focusNode,eventNode" dojoAttachEvent="onpaste:_changing,oncut:_changing" waiRole="textarea" style="text-decoration:none;_padding-bottom:16px;display:block;overflow:auto;" contentEditable="true"></div>'
|
||||
: '<span id="${id}" class="dijitReset">'+
|
||||
'<iframe src="javascript:<html><head><title>${_iframeEditTitle}</title></head><body><script>var _postCreate=window.frameElement?window.frameElement.postCreate:null;if(_postCreate)_postCreate();</script></body></html>"'+
|
||||
' dojoAttachPoint="iframe,styleNode" dojoAttachEvent="onblur:_onIframeBlur" class="dijitInline dijitInputField dijitTextArea"></iframe>')
|
||||
+ '<textarea name="${name}" value="${value}" dojoAttachPoint="formValueNode" style="display:none;"></textarea>'
|
||||
+ ((dojo.isIE || dojo.isSafari) ? '</fieldset>':'</span>')
|
||||
: '<textarea id="${id}" name="${name}" value="${value}" dojoAttachPoint="formValueNode,editNode,focusNode,styleNode" class="dijitInputField dijitTextArea"></textarea>',
|
||||
|
||||
focus: function(){
|
||||
// summary: Received focus, needed for the InlineEditBox widget
|
||||
if(!this.disabled){
|
||||
this._changing(); // set initial height
|
||||
}
|
||||
if(dojo.isMozilla){
|
||||
dijit.focus(this.iframe);
|
||||
}else{
|
||||
dijit.focus(this.focusNode);
|
||||
}
|
||||
},
|
||||
|
||||
setValue: function(/*String*/ value, /*Boolean, optional*/ priorityChange){
|
||||
var editNode = this.editNode;
|
||||
if(typeof value == "string"){
|
||||
editNode.innerHTML = ""; // wipe out old nodes
|
||||
if(value.split){
|
||||
var _this=this;
|
||||
var isFirst = true;
|
||||
dojo.forEach(value.split("\n"), function(line){
|
||||
if(isFirst){ isFirst = false; }
|
||||
else {
|
||||
editNode.appendChild(document.createElement("BR")); // preserve line breaks
|
||||
}
|
||||
editNode.appendChild(document.createTextNode(line)); // use text nodes so that imbedded tags can be edited
|
||||
});
|
||||
}else{
|
||||
editNode.appendChild(document.createTextNode(value));
|
||||
}
|
||||
}else{
|
||||
// blah<BR>blah --> blah\nblah
|
||||
// <P>blah</P><P>blah</P> --> blah\nblah
|
||||
// <DIV>blah</DIV><DIV>blah</DIV> --> blah\nblah
|
||||
// &<> -->&< >
|
||||
value = editNode.innerHTML;
|
||||
if(this.iframe){ // strip sizeNode
|
||||
value = value.replace(/<div><\/div>\r?\n?$/i,"");
|
||||
}
|
||||
value = value.replace(/\s*\r?\n|^\s+|\s+$| /g,"").replace(/>\s+</g,"><").replace(/<\/(p|div)>$|^<(p|div)[^>]*>/gi,"").replace(/([^>])<div>/g,"$1\n").replace(/<\/p>\s*<p[^>]*>|<br[^>]*>/gi,"\n").replace(/<[^>]*>/g,"").replace(/&/gi,"\&").replace(/</gi,"<").replace(/>/gi,">");
|
||||
}
|
||||
this.value = this.formValueNode.value = value;
|
||||
if(this.iframe){
|
||||
var sizeNode = document.createElement('div');
|
||||
editNode.appendChild(sizeNode);
|
||||
var newHeight = sizeNode.offsetTop;
|
||||
if(editNode.scrollWidth > editNode.clientWidth){ newHeight+=16; } // scrollbar space needed?
|
||||
if(this.lastHeight != newHeight){ // cache size so that we don't get a resize event because of a resize event
|
||||
if(newHeight == 0){ newHeight = 16; } // height = 0 causes the browser to not set scrollHeight
|
||||
dojo.contentBox(this.iframe, {h: newHeight});
|
||||
this.lastHeight = newHeight;
|
||||
}
|
||||
editNode.removeChild(sizeNode);
|
||||
}
|
||||
dijit.form.Textarea.superclass.setValue.call(this, this.getValue(), priorityChange);
|
||||
},
|
||||
|
||||
getValue: function(){
|
||||
return this.formValueNode.value.replace(/\r/g,"");
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
dijit.form.Textarea.superclass.postMixInProperties.apply(this,arguments);
|
||||
// don't let the source text be converted to a DOM structure since we just want raw text
|
||||
if(this.srcNodeRef && this.srcNodeRef.innerHTML != ""){
|
||||
this.value = this.srcNodeRef.innerHTML;
|
||||
this.srcNodeRef.innerHTML = "";
|
||||
}
|
||||
if((!this.value || this.value == "") && this.srcNodeRef && this.srcNodeRef.value){
|
||||
this.value = this.srcNodeRef.value;
|
||||
}
|
||||
if(!this.value){ this.value = ""; }
|
||||
this.value = this.value.replace(/\r\n/g,"\n").replace(/>/g,">").replace(/</g,"<").replace(/&/g,"&");
|
||||
if(dojo.isMozilla){
|
||||
// In the case of Firefox an iframe is used and when the text gets focus,
|
||||
// focus is fired from the document object. There isn't a way to put a
|
||||
// waiRole on the document object and as a result screen readers don't
|
||||
// announce the role. As a result screen reader users are lost.
|
||||
//
|
||||
// An additional problem is that the browser gives the document object a
|
||||
// very cryptic accessible name, e.g.
|
||||
// wysiwyg://13/http://archive.dojotoolkit.org/nightly/dojotoolkit/dijit/tests/form/test_InlineEditBox.html
|
||||
// When focus is fired from the document object, the screen reader speaks
|
||||
// the accessible name. The cyptic accessile name is confusing.
|
||||
//
|
||||
// A workaround for both of these problems is to give the iframe's
|
||||
// document a title, the name of which is similar to a role name, i.e.
|
||||
// "edit area". This will be used as the accessible name which will replace
|
||||
// the cryptic name and will also convey the role information to the user.
|
||||
// Because it is read directly to the user, the string must be localized.
|
||||
var _nlsResources = dojo.i18n.getLocalization("dijit", "Textarea");
|
||||
this._iframeEditTitle = _nlsResources.iframeEditTitle;
|
||||
this._iframeFocusTitle = _nlsResources.iframeFocusTitle;
|
||||
var body = this.focusNode = this.editNode = document.createElement('BODY');
|
||||
body.style.margin="0px";
|
||||
body.style.padding="0px";
|
||||
body.style.border="0px";
|
||||
}
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
if(dojo.isIE || dojo.isSafari){
|
||||
this.domNode.style.overflowY = 'hidden';
|
||||
}else if(dojo.isMozilla){
|
||||
var w = this.iframe.contentWindow;
|
||||
try { // #4715: peeking at the title can throw a security exception during iframe setup
|
||||
var title = this.iframe.contentDocument.title;
|
||||
} catch(e) { var title = ''; }
|
||||
if(!w || !title){
|
||||
this.iframe.postCreate = dojo.hitch(this, this.postCreate);
|
||||
return;
|
||||
}
|
||||
var d = w.document;
|
||||
d.getElementsByTagName('HTML')[0].replaceChild(this.editNode, d.getElementsByTagName('BODY')[0]);
|
||||
if(!this.isLeftToRight()){
|
||||
d.getElementsByTagName('HTML')[0].dir = "rtl";
|
||||
}
|
||||
this.iframe.style.overflowY = 'hidden';
|
||||
this.eventNode = d;
|
||||
// this.connect won't destroy this handler cleanly since its on the iframe's window object
|
||||
// resize is a method of window, not document
|
||||
w.addEventListener("resize", dojo.hitch(this, this._changed), false); // resize is only on the window object
|
||||
}else{
|
||||
this.focusNode = this.domNode;
|
||||
}
|
||||
if(this.eventNode){
|
||||
this.connect(this.eventNode, "keypress", this._onKeyPress);
|
||||
this.connect(this.eventNode, "mousemove", this._changed);
|
||||
this.connect(this.eventNode, "focus", this._focused);
|
||||
this.connect(this.eventNode, "blur", this._blurred);
|
||||
}
|
||||
if(this.editNode){
|
||||
this.connect(this.editNode, "change", this._changed); // needed for mouse paste events per #3479
|
||||
}
|
||||
this.inherited('postCreate', arguments);
|
||||
},
|
||||
|
||||
// event handlers, you can over-ride these in your own subclasses
|
||||
_focused: function(e){
|
||||
dojo.addClass(this.iframe||this.domNode, "dijitInputFieldFocused");
|
||||
this._changed(e);
|
||||
},
|
||||
|
||||
_blurred: function(e){
|
||||
dojo.removeClass(this.iframe||this.domNode, "dijitInputFieldFocused");
|
||||
this._changed(e, true);
|
||||
},
|
||||
|
||||
_onIframeBlur: function(){
|
||||
// Reset the title back to "edit area".
|
||||
this.iframe.contentDocument.title = this._iframeEditTitle;
|
||||
},
|
||||
|
||||
_onKeyPress: function(e){
|
||||
if(e.keyCode == dojo.keys.TAB && !e.shiftKey && !e.ctrlKey && !e.altKey && this.iframe){
|
||||
// Pressing the tab key in the iframe (with designMode on) will cause the
|
||||
// entry of a tab character so we have to trap that here. Since we don't
|
||||
// know the next focusable object we put focus on the iframe and then the
|
||||
// user has to press tab again (which then does the expected thing).
|
||||
// A problem with that is that the screen reader user hears "edit area"
|
||||
// announced twice which causes confusion. By setting the
|
||||
// contentDocument's title to "edit area frame" the confusion should be
|
||||
// eliminated.
|
||||
this.iframe.contentDocument.title = this._iframeFocusTitle;
|
||||
// Place focus on the iframe. A subsequent tab or shift tab will put focus
|
||||
// on the correct control.
|
||||
// Note: Can't use this.focus() because that results in a call to
|
||||
// dijit.focus and if that receives an iframe target it will set focus
|
||||
// on the iframe's contentWindow.
|
||||
this.iframe.focus(); // this.focus(); won't work
|
||||
dojo.stopEvent(e);
|
||||
}else if(e.keyCode == dojo.keys.ENTER){
|
||||
e.stopPropagation();
|
||||
}else if(this.inherited("_onKeyPress", arguments) && this.iframe){
|
||||
// #3752:
|
||||
// The key press will not make it past the iframe.
|
||||
// If a widget is listening outside of the iframe, (like InlineEditBox)
|
||||
// it will not hear anything.
|
||||
// Create an equivalent event so everyone else knows what is going on.
|
||||
var te = document.createEvent("KeyEvents");
|
||||
te.initKeyEvent("keypress", true, true, null, e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, e.keyCode, e.charCode);
|
||||
this.iframe.dispatchEvent(te);
|
||||
}
|
||||
this._changing();
|
||||
},
|
||||
|
||||
_changing: function(e){
|
||||
// summary: event handler for when a change is imminent
|
||||
setTimeout(dojo.hitch(this, "_changed", e, false), 1);
|
||||
},
|
||||
|
||||
_changed: function(e, priorityChange){
|
||||
// summary: event handler for when a change has already happened
|
||||
if(this.iframe && this.iframe.contentDocument.designMode != "on"){
|
||||
this.iframe.contentDocument.designMode="on"; // in case this failed on init due to being hidden
|
||||
}
|
||||
this.setValue(null, priorityChange);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.TimeTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.TimeTextBox"] = true;
|
||||
dojo.provide("dijit.form.TimeTextBox");
|
||||
|
||||
dojo.require("dojo.date");
|
||||
dojo.require("dojo.date.locale");
|
||||
dojo.require("dojo.date.stamp");
|
||||
dojo.require("dijit._TimePicker");
|
||||
dojo.require("dijit.form.ValidationTextBox");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.TimeTextBox",
|
||||
dijit.form.RangeBoundTextBox,
|
||||
{
|
||||
// summary:
|
||||
// A validating, serializable, range-bound date text box.
|
||||
|
||||
// constraints object: min, max
|
||||
regExpGen: dojo.date.locale.regexp,
|
||||
compare: dojo.date.compare,
|
||||
format: function(/*Date*/ value, /*Object*/ constraints){
|
||||
if(!value || value.toString() == this._invalid){ return null; }
|
||||
return dojo.date.locale.format(value, constraints);
|
||||
},
|
||||
parse: dojo.date.locale.parse,
|
||||
serialize: dojo.date.stamp.toISOString,
|
||||
|
||||
value: new Date(""), // NaN
|
||||
_invalid: (new Date("")).toString(), // NaN
|
||||
|
||||
_popupClass: "dijit._TimePicker",
|
||||
|
||||
postMixInProperties: function(){
|
||||
//dijit.form.RangeBoundTextBox.prototype.postMixInProperties.apply(this, arguments);
|
||||
this.inherited("postMixInProperties",arguments);
|
||||
var constraints = this.constraints;
|
||||
constraints.selector = 'time';
|
||||
if(typeof constraints.min == "string"){ constraints.min = dojo.date.stamp.fromISOString(constraints.min); }
|
||||
if(typeof constraints.max == "string"){ constraints.max = dojo.date.stamp.fromISOString(constraints.max); }
|
||||
},
|
||||
|
||||
_onFocus: function(/*Event*/ evt){
|
||||
// summary: open the TimePicker popup
|
||||
this._open();
|
||||
},
|
||||
|
||||
setValue: function(/*Date*/ value, /*Boolean, optional*/ priorityChange){
|
||||
// summary:
|
||||
// Sets the date on this textbox
|
||||
this.inherited('setValue', arguments);
|
||||
if(this._picker){
|
||||
// #3948: fix blank date on popup only
|
||||
if(!value || value.toString() == this._invalid){value=new Date();}
|
||||
this._picker.setValue(value);
|
||||
}
|
||||
},
|
||||
|
||||
_open: function(){
|
||||
// summary:
|
||||
// opens the TimePicker, and sets the onValueSelected value
|
||||
|
||||
if(this.disabled){return;}
|
||||
|
||||
var self = this;
|
||||
|
||||
if(!this._picker){
|
||||
var popupProto=dojo.getObject(this._popupClass, false);
|
||||
this._picker = new popupProto({
|
||||
onValueSelected: function(value){
|
||||
|
||||
self.focus(); // focus the textbox before the popup closes to avoid reopening the popup
|
||||
setTimeout(dojo.hitch(self, "_close"), 1); // allow focus time to take
|
||||
|
||||
// this will cause InlineEditBox and other handlers to do stuff so make sure it's last
|
||||
dijit.form.TimeTextBox.superclass.setValue.call(self, value, true);
|
||||
},
|
||||
lang: this.lang,
|
||||
constraints:this.constraints,
|
||||
isDisabledDate: function(/*Date*/ date){
|
||||
// summary:
|
||||
// disables dates outside of the min/max of the TimeTextBox
|
||||
return self.constraints && (dojo.date.compare(self.constraints.min,date) > 0 || dojo.date.compare(self.constraints.max,date) < 0);
|
||||
}
|
||||
});
|
||||
this._picker.setValue(this.getValue() || new Date());
|
||||
}
|
||||
if(!this._opened){
|
||||
dijit.popup.open({
|
||||
parent: this,
|
||||
popup: this._picker,
|
||||
around: this.domNode,
|
||||
onCancel: dojo.hitch(this, this._close),
|
||||
onClose: function(){ self._opened=false; }
|
||||
});
|
||||
this._opened=true;
|
||||
}
|
||||
|
||||
dojo.marginBox(this._picker.domNode,{ w:this.domNode.offsetWidth });
|
||||
},
|
||||
|
||||
_close: function(){
|
||||
if(this._opened){
|
||||
dijit.popup.close(this._picker);
|
||||
this._opened=false;
|
||||
}
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
// summary: called magically when focus has shifted away from this widget and it's dropdown
|
||||
this._close();
|
||||
this.inherited('_onBlur', arguments);
|
||||
// don't focus on <input>. the user has explicitly focused on something else.
|
||||
},
|
||||
|
||||
getDisplayedValue:function(){
|
||||
return this.textbox.value;
|
||||
},
|
||||
|
||||
setDisplayedValue:function(/*String*/ value){
|
||||
this.textbox.value=value;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form.ValidationTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form.ValidationTextBox"] = true;
|
||||
dojo.provide("dijit.form.ValidationTextBox");
|
||||
|
||||
dojo.require("dojo.i18n");
|
||||
|
||||
dojo.require("dijit.form.TextBox");
|
||||
dojo.require("dijit.Tooltip");
|
||||
|
||||
dojo.requireLocalization("dijit.form", "validate", null, "ko,zh-cn,zh,ja,zh-tw,ru,it,hu,ROOT,fr,pt,pl,es,de,cs");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.ValidationTextBox",
|
||||
dijit.form.TextBox,
|
||||
{
|
||||
// summary:
|
||||
// A subclass of TextBox.
|
||||
// Over-ride isValid in subclasses to perform specific kinds of validation.
|
||||
|
||||
templateString:"<table style=\"display: -moz-inline-stack;\" class=\"dijit dijitReset dijitInlineTable\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\"\n\tdojoAttachEvent=\"onmouseenter:_onMouse,onmouseleave:_onMouse\" waiRole=\"presentation\"\n\t><tr class=\"dijitReset\"\n\t\t><td class=\"dijitReset dijitInputField\" width=\"100%\"\n\t\t\t><input dojoAttachPoint='textbox,focusNode' dojoAttachEvent='onfocus,onblur:_onMouse,onkeyup,onkeypress:_onKeyPress' autocomplete=\"off\"\n\t\t\ttype='${type}' name='${name}'\n\t\t/></td\n\t\t><td class=\"dijitReset dijitValidationIconField\" width=\"0%\"\n\t\t\t><div dojoAttachPoint='iconNode' class='dijitValidationIcon'></div><div class='dijitValidationIconText'>Χ</div\n\t\t></td\n\t></tr\n></table>\n",
|
||||
baseClass: "dijitTextBox",
|
||||
|
||||
// default values for new subclass properties
|
||||
// required: Boolean
|
||||
// Can be true or false, default is false.
|
||||
required: false,
|
||||
// promptMessage: String
|
||||
// Hint string
|
||||
promptMessage: "",
|
||||
// invalidMessage: String
|
||||
// The message to display if value is invalid.
|
||||
invalidMessage: "\x00", // read from the message file if not overridden
|
||||
// constraints: Object
|
||||
// user-defined object needed to pass parameters to the validator functions
|
||||
constraints: {},
|
||||
// regExp: String
|
||||
// regular expression string used to validate the input
|
||||
// Do not specify both regExp and regExpGen
|
||||
regExp: ".*",
|
||||
// regExpGen: Function
|
||||
// user replaceable function used to generate regExp when dependent on constraints
|
||||
// Do not specify both regExp and regExpGen
|
||||
regExpGen: function(constraints){ return this.regExp; },
|
||||
|
||||
// state: String
|
||||
// Shows current state (ie, validation result) of input (Normal, Warning, or Error)
|
||||
state: "",
|
||||
|
||||
setValue: function(){
|
||||
this.inherited('setValue', arguments);
|
||||
this.validate(false);
|
||||
},
|
||||
|
||||
validator: function(value,constraints){
|
||||
// summary: user replaceable function used to validate the text input against the regular expression.
|
||||
return (new RegExp("^(" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
|
||||
(!this.required || !this._isEmpty(value)) &&
|
||||
(this._isEmpty(value) || this.parse(value, constraints) !== null);
|
||||
},
|
||||
|
||||
isValid: function(/* Boolean*/ isFocused){
|
||||
// summary: Need to over-ride with your own validation code in subclasses
|
||||
return this.validator(this.textbox.value, this.constraints);
|
||||
},
|
||||
|
||||
_isEmpty: function(value){
|
||||
// summary: Checks for whitespace
|
||||
return /^\s*$/.test(value); // Boolean
|
||||
},
|
||||
|
||||
getErrorMessage: function(/* Boolean*/ isFocused){
|
||||
// summary: return an error message to show if appropriate
|
||||
return this.invalidMessage;
|
||||
},
|
||||
|
||||
getPromptMessage: function(/* Boolean*/ isFocused){
|
||||
// summary: return a hint to show if appropriate
|
||||
return this.promptMessage;
|
||||
},
|
||||
|
||||
validate: function(/* Boolean*/ isFocused){
|
||||
// summary:
|
||||
// Called by oninit, onblur, and onkeypress.
|
||||
// description:
|
||||
// Show missing or invalid messages if appropriate, and highlight textbox field.
|
||||
var message = "";
|
||||
var isValid = this.isValid(isFocused);
|
||||
var isEmpty = this._isEmpty(this.textbox.value);
|
||||
this.state = (isValid || (!this._hasBeenBlurred && isEmpty)) ? "" : "Error";
|
||||
this._setStateClass();
|
||||
dijit.setWaiState(this.focusNode, "invalid", (isValid? "false" : "true"));
|
||||
if(isFocused){
|
||||
if(isEmpty){
|
||||
message = this.getPromptMessage(true);
|
||||
}
|
||||
if(!message && !isValid){
|
||||
message = this.getErrorMessage(true);
|
||||
}
|
||||
}
|
||||
this._displayMessage(message);
|
||||
},
|
||||
|
||||
// currently displayed message
|
||||
_message: "",
|
||||
|
||||
_displayMessage: function(/*String*/ message){
|
||||
if(this._message == message){ return; }
|
||||
this._message = message;
|
||||
this.displayMessage(message);
|
||||
},
|
||||
|
||||
displayMessage: function(/*String*/ message){
|
||||
// summary:
|
||||
// User overridable method to display validation errors/hints.
|
||||
// By default uses a tooltip.
|
||||
if(message){
|
||||
dijit.showTooltip(message, this.domNode);
|
||||
}else{
|
||||
dijit.hideTooltip(this.domNode);
|
||||
}
|
||||
},
|
||||
|
||||
_hasBeenBlurred: false,
|
||||
|
||||
_onBlur: function(evt){
|
||||
this._hasBeenBlurred = true;
|
||||
this.validate(false);
|
||||
this.inherited('_onBlur', arguments);
|
||||
},
|
||||
|
||||
onfocus: function(evt){
|
||||
// TODO: change to _onFocus?
|
||||
this.validate(true);
|
||||
this._onMouse(evt); // update CSS classes
|
||||
},
|
||||
|
||||
onkeyup: function(evt){
|
||||
this.onfocus(evt);
|
||||
},
|
||||
|
||||
//////////// INITIALIZATION METHODS ///////////////////////////////////////
|
||||
constructor: function(){
|
||||
this.constraints = {};
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.inherited('postMixInProperties', arguments);
|
||||
this.constraints.locale=this.lang;
|
||||
this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
|
||||
if(this.invalidMessage == "\x00"){ this.invalidMessage = this.messages.invalidMessage; }
|
||||
var p = this.regExpGen(this.constraints);
|
||||
this.regExp = p;
|
||||
// make value a string for all types so that form reset works well
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.MappedTextBox",
|
||||
dijit.form.ValidationTextBox,
|
||||
{
|
||||
// summary:
|
||||
// A subclass of ValidationTextBox.
|
||||
// Provides a hidden input field and a serialize method to override
|
||||
|
||||
serialize: function(val, /*Object?*/options){
|
||||
// summary: user replaceable function used to convert the getValue() result to a String
|
||||
return (val.toString ? val.toString() : "");
|
||||
},
|
||||
|
||||
toString: function(){
|
||||
// summary: display the widget as a printable string using the widget's value
|
||||
var val = this.filter(this.getValue());
|
||||
return (val!=null) ? ((typeof val == "string") ? val : this.serialize(val, this.constraints)) : "";
|
||||
},
|
||||
|
||||
validate: function(){
|
||||
this.valueNode.value = this.toString();
|
||||
this.inherited('validate', arguments);
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
var textbox = this.textbox;
|
||||
var valueNode = (this.valueNode = document.createElement("input"));
|
||||
valueNode.setAttribute("type", textbox.type);
|
||||
valueNode.setAttribute("value", this.toString());
|
||||
dojo.style(valueNode, "display", "none");
|
||||
valueNode.name = this.textbox.name;
|
||||
this.textbox.name = "_" + this.textbox.name + "_displayed_";
|
||||
this.textbox.removeAttribute("name");
|
||||
dojo.place(valueNode, textbox, "after");
|
||||
|
||||
this.inherited('postCreate', arguments);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form.RangeBoundTextBox",
|
||||
dijit.form.MappedTextBox,
|
||||
{
|
||||
// summary:
|
||||
// A subclass of MappedTextBox.
|
||||
// Tests for a value out-of-range
|
||||
/*===== contraints object:
|
||||
// min: Number
|
||||
// Minimum signed value. Default is -Infinity
|
||||
min: undefined,
|
||||
// max: Number
|
||||
// Maximum signed value. Default is +Infinity
|
||||
max: undefined,
|
||||
=====*/
|
||||
|
||||
// rangeMessage: String
|
||||
// The message to display if value is out-of-range
|
||||
rangeMessage: "",
|
||||
|
||||
compare: function(val1, val2){
|
||||
// summary: compare 2 values
|
||||
return val1 - val2;
|
||||
},
|
||||
|
||||
rangeCheck: function(/* Number */ primitive, /* Object */ constraints){
|
||||
// summary: user replaceable function used to validate the range of the numeric input value
|
||||
var isMin = (typeof constraints.min != "undefined");
|
||||
var isMax = (typeof constraints.max != "undefined");
|
||||
if(isMin || isMax){
|
||||
return (!isMin || this.compare(primitive,constraints.min) >= 0) &&
|
||||
(!isMax || this.compare(primitive,constraints.max) <= 0);
|
||||
}else{ return true; }
|
||||
},
|
||||
|
||||
isInRange: function(/* Boolean*/ isFocused){
|
||||
// summary: Need to over-ride with your own validation code in subclasses
|
||||
return this.rangeCheck(this.getValue(), this.constraints);
|
||||
},
|
||||
|
||||
isValid: function(/* Boolean*/ isFocused){
|
||||
return this.inherited('isValid', arguments) &&
|
||||
((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused));
|
||||
},
|
||||
|
||||
getErrorMessage: function(/* Boolean*/ isFocused){
|
||||
if(dijit.form.RangeBoundTextBox.superclass.isValid.call(this, false) && !this.isInRange(isFocused)){ return this.rangeMessage; }
|
||||
else{ return this.inherited('getErrorMessage', arguments); }
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
this.inherited('postMixInProperties', arguments);
|
||||
if(!this.rangeMessage){
|
||||
this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
|
||||
this.rangeMessage = this.messages.rangeMessage;
|
||||
}
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
this.inherited('postCreate', arguments);
|
||||
if(typeof this.constraints.min != "undefined"){
|
||||
dijit.setWaiState(this.focusNode, "valuemin", this.constraints.min);
|
||||
}
|
||||
if(typeof this.constraints.max != "undefined"){
|
||||
dijit.setWaiState(this.focusNode, "valuemax", this.constraints.max);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form._DropDownTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form._DropDownTextBox"] = true;
|
||||
dojo.provide("dijit.form._DropDownTextBox");
|
||||
|
||||
dojo.declare(
|
||||
"dijit.form._DropDownTextBox",
|
||||
null,
|
||||
{
|
||||
// summary:
|
||||
// Mixin text box with drop down
|
||||
|
||||
templateString:"<table class=\"dijit dijitReset dijitInline dijitLeft\" baseClass=\"${baseClass}\" cellspacing=\"0\" cellpadding=\"0\"\n\tid=\"widget_${id}\" name=\"${name}\" dojoAttachEvent=\"onmouseover:_onMouse,onmouseout:_onMouse\" waiRole=\"presentation\"\n\t><tr\n\t\t><td class='dijitReset dijitStretch dijitComboBoxInput'\n\t\t\t><input class='XdijitInputField' type=\"text\" autocomplete=\"off\" name=\"${name}\"\n\t\t\tdojoAttachEvent=\"onkeypress, onkeyup, onfocus, onblur, compositionend\"\n\t\t\tdojoAttachPoint=\"textbox,focusNode\" id='${id}'\n\t\t\ttabIndex='${tabIndex}' size='${size}' maxlength='${maxlength}'\n\t\t\twaiRole=\"combobox\"\n\t\t></td\n\t\t><td class='dijitReset dijitRight dijitButtonNode dijitDownArrowButton'\n\t\t\tdojoAttachPoint=\"downArrowNode\"\n\t\t\tdojoAttachEvent=\"ondijitclick:_onArrowClick,onmousedown:_onMouse,onmouseup:_onMouse,onmouseover:_onMouse,onmouseout:_onMouse\"\n\t\t><div class=\"dijitDownArrowButtonInner\" waiRole=\"presentation\" tabIndex=\"-1\">\n\t\t\t<div class=\"dijit_a11y dijitDownArrowButtonChar\">▼</div>\n\t\t</div>\n\t</td></tr>\n</table>\n",
|
||||
|
||||
baseClass:"dijitComboBox",
|
||||
|
||||
// hasDownArrow: Boolean
|
||||
// Set this textbox to have a down arrow button
|
||||
// Defaults to true
|
||||
hasDownArrow:true,
|
||||
|
||||
// _popupWidget: Widget
|
||||
// link to the popup widget created by makePopop
|
||||
_popupWidget:null,
|
||||
|
||||
// _hasMasterPopup: Boolean
|
||||
// Flag that determines if this widget should share one popup per widget prototype,
|
||||
// or create one popup per widget instance.
|
||||
// If true, then makePopup() creates one popup per widget prototype.
|
||||
// If false, then makePopup() creates one popup per widget instance.
|
||||
_hasMasterPopup:false,
|
||||
|
||||
// _popupClass: String
|
||||
// Class of master popup (dijit.form._ComboBoxMenu)
|
||||
_popupClass:"",
|
||||
|
||||
// _popupArgs: Object
|
||||
// Object to pass to popup widget on initialization
|
||||
_popupArgs:{},
|
||||
|
||||
// _hasFocus: Boolean
|
||||
// Represents focus state of the textbox
|
||||
_hasFocus:false,
|
||||
|
||||
_arrowPressed: function(){
|
||||
if(!this.disabled&&this.hasDownArrow){
|
||||
dojo.addClass(this.downArrowNode, "dijitArrowButtonActive");
|
||||
}
|
||||
},
|
||||
|
||||
_arrowIdle: function(){
|
||||
if(!this.disabled&&this.hasDownArrow){
|
||||
dojo.removeClass(this.downArrowNode, "dojoArrowButtonPushed");
|
||||
}
|
||||
},
|
||||
|
||||
makePopup: function(){
|
||||
// summary:
|
||||
// create popup widget on demand
|
||||
var _this=this;
|
||||
function _createNewPopup(){
|
||||
// common code from makePopup
|
||||
var node=document.createElement("div");
|
||||
document.body.appendChild(node);
|
||||
var popupProto=dojo.getObject(_this._popupClass, false);
|
||||
return new popupProto(_this._popupArgs, node);
|
||||
}
|
||||
// this code only runs if there is no popup reference
|
||||
if(!this._popupWidget){
|
||||
// does this widget have one "master" popup?
|
||||
if(this._hasMasterPopup){
|
||||
// does the master popup not exist yet?
|
||||
var parentClass = dojo.getObject(this.declaredClass, false);
|
||||
if(!parentClass.prototype._popupWidget){
|
||||
// create the master popup for the first time
|
||||
parentClass.prototype._popupWidget=_createNewPopup();
|
||||
}
|
||||
// assign master popup to local link
|
||||
this._popupWidget=parentClass.prototype._popupWidget;
|
||||
}else{
|
||||
// if master popup is not being used, create one popup per widget instance
|
||||
this._popupWidget=_createNewPopup();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_onArrowClick: function(){
|
||||
// summary: callback when arrow is clicked
|
||||
if(this.disabled){
|
||||
return;
|
||||
}
|
||||
this.focus();
|
||||
this.makePopup();
|
||||
if(this._isShowingNow){
|
||||
this._hideResultList();
|
||||
}else{
|
||||
// forces full population of results, if they click
|
||||
// on the arrow it means they want to see more options
|
||||
this._openResultList();
|
||||
}
|
||||
},
|
||||
|
||||
_hideResultList: function(){
|
||||
if(this._isShowingNow){
|
||||
dijit.popup.close();
|
||||
this._arrowIdle();
|
||||
this._isShowingNow=false;
|
||||
}
|
||||
},
|
||||
|
||||
_openResultList:function(){
|
||||
// summary:
|
||||
// any code that needs to happen before the popup appears.
|
||||
// creating the popupWidget contents etc.
|
||||
this._showResultList();
|
||||
},
|
||||
|
||||
onfocus:function(){
|
||||
this._hasFocus=true;
|
||||
},
|
||||
|
||||
onblur:function(){
|
||||
this._arrowIdle();
|
||||
this._hasFocus=false;
|
||||
// removeClass dijitInputFieldFocused
|
||||
dojo.removeClass(this.nodeWithBorder, "dijitInputFieldFocused");
|
||||
// hide the Tooltip
|
||||
this.validate(false);
|
||||
},
|
||||
|
||||
onkeypress: function(/*Event*/ evt){
|
||||
// summary: generic handler for popup keyboard events
|
||||
if(evt.ctrlKey || evt.altKey){
|
||||
return;
|
||||
}
|
||||
switch(evt.keyCode){
|
||||
case dojo.keys.PAGE_DOWN:
|
||||
case dojo.keys.DOWN_ARROW:
|
||||
if(!this._isShowingNow||this._prev_key_esc){
|
||||
this.makePopup();
|
||||
this._arrowPressed();
|
||||
this._openResultList();
|
||||
}
|
||||
dojo.stopEvent(evt);
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = false;
|
||||
break;
|
||||
|
||||
case dojo.keys.PAGE_UP:
|
||||
case dojo.keys.UP_ARROW:
|
||||
case dojo.keys.ENTER:
|
||||
// prevent default actions
|
||||
dojo.stopEvent(evt);
|
||||
// fall through
|
||||
case dojo.keys.ESCAPE:
|
||||
case dojo.keys.TAB:
|
||||
if(this._isShowingNow){
|
||||
this._prev_key_backspace = false;
|
||||
this._prev_key_esc = (evt.keyCode==dojo.keys.ESCAPE);
|
||||
this._hideResultList();
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
compositionend: function(/*Event*/ evt){
|
||||
// summary: When inputting characters using an input method, such as Asian
|
||||
// languages, it will generate this event instead of onKeyDown event
|
||||
this.onkeypress({charCode:-1});
|
||||
},
|
||||
|
||||
_showResultList: function(){
|
||||
// Our dear friend IE doesnt take max-height so we need to calculate that on our own every time
|
||||
this._hideResultList();
|
||||
var childs = this._popupWidget.getListLength ? this._popupWidget.getItems() : [this._popupWidget.domNode];
|
||||
|
||||
if(childs.length){
|
||||
var visibleCount = Math.min(childs.length,this.maxListLength);
|
||||
with(this._popupWidget.domNode.style){
|
||||
// trick to get the dimensions of the popup
|
||||
// TODO: doesn't dijit.popup.open() do this automatically?
|
||||
display="";
|
||||
width="";
|
||||
height="";
|
||||
}
|
||||
this._arrowPressed();
|
||||
// hide the tooltip
|
||||
this._displayMessage("");
|
||||
var best=this.open();
|
||||
// #3212: only set auto scroll bars if necessary
|
||||
// prevents issues with scroll bars appearing when they shouldn't when node is made wider (fractional pixels cause this)
|
||||
var popupbox=dojo.marginBox(this._popupWidget.domNode);
|
||||
this._popupWidget.domNode.style.overflow=((best.h==popupbox.h)&&(best.w==popupbox.w))?"hidden":"auto";
|
||||
dojo.marginBox(this._popupWidget.domNode, {h:best.h,w:Math.max(best.w,this.domNode.offsetWidth)});
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
getDisplayedValue:function(){
|
||||
return this.textbox.value;
|
||||
},
|
||||
|
||||
setDisplayedValue:function(/*String*/ value){
|
||||
this.textbox.value=value;
|
||||
},
|
||||
|
||||
uninitialize:function(){
|
||||
if(this._popupWidget){
|
||||
this._hideResultList();
|
||||
this._popupWidget.destroy()
|
||||
};
|
||||
},
|
||||
|
||||
open:function(){
|
||||
this.makePopup();
|
||||
var self=this;
|
||||
self._isShowingNow=true;
|
||||
return dijit.popup.open({
|
||||
popup: this._popupWidget,
|
||||
around: this.domNode,
|
||||
parent: this
|
||||
});
|
||||
},
|
||||
|
||||
_onBlur: function(){
|
||||
// summary: called magically when focus has shifted away from this widget and it's dropdown
|
||||
this._hideResultList();
|
||||
},
|
||||
|
||||
postMixInProperties:function(){
|
||||
this.baseClass=this.hasDownArrow?this.baseClass:this.baseClass+"NoArrow";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
|
||||
dojo._hasResource["dijit.form._FormWidget"] = true;
|
||||
dojo.provide("dijit.form._FormWidget");
|
||||
|
||||
dojo.require("dijit._Widget");
|
||||
dojo.require("dijit._Templated");
|
||||
|
||||
dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated],
|
||||
{
|
||||
/*
|
||||
Summary:
|
||||
FormElement widgets correspond to native HTML elements such as <input> or <button> or <select>.
|
||||
Each FormElement represents a single input value, and has a (possibly hidden) <input> element,
|
||||
to which it serializes its input value, so that form submission (either normal submission or via FormBind?)
|
||||
works as expected.
|
||||
|
||||
All these widgets should have these attributes just like native HTML input elements.
|
||||
You can set them during widget construction, but after that they are read only.
|
||||
|
||||
They also share some common methods.
|
||||
*/
|
||||
|
||||
// baseClass: String
|
||||
// Root CSS class of the widget (ex: dijitTextBox), used to add CSS classes of widget
|
||||
// (ex: "dijitTextBox dijitTextBoxInvalid dijitTextBoxFocused dijitTextBoxInvalidFocused")
|
||||
// See _setStateClass().
|
||||
baseClass: "",
|
||||
|
||||
// value: String
|
||||
// Corresponds to the native HTML <input> element's attribute.
|
||||
value: "",
|
||||
|
||||
// name: String
|
||||
// Name used when submitting form; same as "name" attribute or plain HTML elements
|
||||
name: "",
|
||||
|
||||
// id: String
|
||||
// Corresponds to the native HTML <input> element's attribute.
|
||||
// Also becomes the id for the widget.
|
||||
id: "",
|
||||
|
||||
// alt: String
|
||||
// Corresponds to the native HTML <input> element's attribute.
|
||||
alt: "",
|
||||
|
||||
// type: String
|
||||
// Corresponds to the native HTML <input> element's attribute.
|
||||
type: "text",
|
||||
|
||||
// tabIndex: Integer
|
||||
// Order fields are traversed when user hits the tab key
|
||||
tabIndex: "0",
|
||||
|
||||
// disabled: Boolean
|
||||
// Should this widget respond to user input?
|
||||
// In markup, this is specified as "disabled='disabled'", or just "disabled".
|
||||
disabled: false,
|
||||
|
||||
// intermediateChanges: Boolean
|
||||
// Fires onChange for each value change or only on demand
|
||||
intermediateChanges: false,
|
||||
|
||||
// These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are.
|
||||
// Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
|
||||
// directly in the template as read by the parser in order to function. IE is known to specifically
|
||||
// require the 'name' attribute at element creation time.
|
||||
attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
|
||||
{id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}),
|
||||
|
||||
setDisabled: function(/*Boolean*/ disabled){
|
||||
// summary:
|
||||
// Set disabled state of widget.
|
||||
|
||||
this.domNode.disabled = this.disabled = disabled;
|
||||
if(this.focusNode){
|
||||
this.focusNode.disabled = disabled;
|
||||
}
|
||||
if(disabled){
|
||||
//reset those, because after the domNode is disabled, we can no longer receive
|
||||
//mouse related events, see #4200
|
||||
this._hovering = false;
|
||||
this._active = false;
|
||||
}
|
||||
dijit.setWaiState(this.focusNode || this.domNode, "disabled", disabled);
|
||||
this._setStateClass();
|
||||
},
|
||||
|
||||
|
||||
_onMouse : function(/*Event*/ event){
|
||||
// summary:
|
||||
// Sets _hovering, _active, and stateModifier properties depending on mouse state,
|
||||
// then calls setStateClass() to set appropriate CSS classes for this.domNode.
|
||||
//
|
||||
// To get a different CSS class for hover, send onmouseover and onmouseout events to this method.
|
||||
// To get a different CSS class while mouse button is depressed, send onmousedown to this method.
|
||||
|
||||
var mouseNode = event.target;
|
||||
if(mouseNode && mouseNode.getAttribute){
|
||||
this.stateModifier = mouseNode.getAttribute("stateModifier") || "";
|
||||
}
|
||||
|
||||
if(!this.disabled){
|
||||
switch(event.type){
|
||||
case "mouseenter" :
|
||||
case "mouseover" :
|
||||
this._hovering = true;
|
||||
break;
|
||||
|
||||
case "mouseout" :
|
||||
case "mouseleave" :
|
||||
this._hovering = false;
|
||||
break;
|
||||
|
||||
case "mousedown" :
|
||||
this._active = true;
|
||||
// set a global event to handle mouseup, so it fires properly
|
||||
// even if the cursor leaves the button
|
||||
var self = this;
|
||||
// #2685: use this.connect and disconnect so destroy works properly
|
||||
var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
|
||||
self._active = false;
|
||||
self._setStateClass();
|
||||
self.disconnect(mouseUpConnector);
|
||||
});
|
||||
break;
|
||||
}
|
||||
this._setStateClass();
|
||||
}
|
||||
},
|
||||
|
||||
isFocusable: function(){
|
||||
return !this.disabled && (dojo.style(this.domNode, "display") != "none");
|
||||
},
|
||||
|
||||
focus: function(){
|
||||
dijit.focus(this.focusNode);
|
||||
},
|
||||
|
||||
_setStateClass: function(){
|
||||
// summary
|
||||
// Update the visual state of the widget by setting the css classes on this.domNode
|
||||
// (or this.stateNode if defined) by combining this.baseClass with
|
||||
// various suffixes that represent the current widget state(s).
|
||||
//
|
||||
// In the case where a widget has multiple
|
||||
// states, it sets the class based on all possible
|
||||
// combinations. For example, an invalid form widget that is being hovered
|
||||
// will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
|
||||
//
|
||||
// For complex widgets with multiple regions, there can be various hover/active states,
|
||||
// such as "Hover" or "CloseButtonHover" (for tab buttons).
|
||||
// This is controlled by a stateModifier="CloseButton" attribute on the close button node.
|
||||
//
|
||||
// The widget may have one or more of the following states, determined
|
||||
// by this.state, this.checked, this.valid, and this.selected:
|
||||
// Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
|
||||
// Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
|
||||
// Selected - ex: currently selected tab will have this.selected==true
|
||||
//
|
||||
// In addition, it may have at most one of the following states,
|
||||
// based on this.disabled and flags set in _onMouse (this._active, this._hovering, this._focused):
|
||||
// Disabled - if the widget is disabled
|
||||
// Active - if the mouse (or space/enter key?) is being pressed down
|
||||
// Focused - if the widget has focus
|
||||
// Hover - if the mouse is over the widget
|
||||
//
|
||||
// (even if multiple af the above conditions are true we only pick the first matching one)
|
||||
|
||||
|
||||
// Get original (non state related, non baseClass related) class specified in template
|
||||
if(!("staticClass" in this)){
|
||||
this.staticClass = (this.stateNode||this.domNode).className;
|
||||
}
|
||||
|
||||
// Compute new set of classes
|
||||
var classes = [ this.baseClass ];
|
||||
|
||||
function multiply(modifier){
|
||||
classes=classes.concat(dojo.map(classes, function(c){ return c+modifier; }));
|
||||
}
|
||||
|
||||
if(this.checked){
|
||||
multiply("Checked");
|
||||
}
|
||||
if(this.state){
|
||||
multiply(this.state);
|
||||
}
|
||||
if(this.selected){
|
||||
multiply("Selected");
|
||||
}
|
||||
|
||||
// Only one of these four can be applied.
|
||||
// Active trumps Focused, Focused trumps Hover, and Disabled trumps all.
|
||||
if(this.disabled){
|
||||
multiply("Disabled");
|
||||
}else if(this._active){
|
||||
multiply(this.stateModifier+"Active");
|
||||
}else if(this._focused){
|
||||
multiply("Focused");
|
||||
}else if(this._hovering){
|
||||
multiply(this.stateModifier+"Hover");
|
||||
}
|
||||
|
||||
(this.stateNode || this.domNode).className = this.staticClass + " " + classes.join(" ");
|
||||
},
|
||||
|
||||
onChange: function(newValue){
|
||||
// summary: callback when value is changed
|
||||
},
|
||||
|
||||
postCreate: function(){
|
||||
this.setValue(this.value, null); // null reserved for initial value
|
||||
this.setDisabled(this.disabled);
|
||||
this._setStateClass();
|
||||
},
|
||||
|
||||
setValue: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
|
||||
// summary: set the value of the widget.
|
||||
this._lastValue = newValue;
|
||||
dijit.setWaiState(this.focusNode || this.domNode, "valuenow", this.forWaiValuenow());
|
||||
if(this._lastValueReported == undefined && priorityChange === null){ // don't report the initial value
|
||||
this._lastValueReported = newValue;
|
||||
}
|
||||
if((this.intermediateChanges || priorityChange) && newValue !== this._lastValueReported){
|
||||
this._lastValueReported = newValue;
|
||||
this.onChange(newValue);
|
||||
}
|
||||
},
|
||||
|
||||
getValue: function(){
|
||||
// summary: get the value of the widget.
|
||||
return this._lastValue;
|
||||
},
|
||||
|
||||
undo: function(){
|
||||
// summary: restore the value to the last value passed to onChange
|
||||
this.setValue(this._lastValueReported, false);
|
||||
},
|
||||
|
||||
_onKeyPress: function(e){
|
||||
if(e.keyCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){
|
||||
var v = this.getValue();
|
||||
var lv = this._lastValueReported;
|
||||
// Equality comparison of objects such as dates are done by reference so
|
||||
// two distinct objects are != even if they have the same data. So use
|
||||
// toStrings in case the values are objects.
|
||||
if((typeof lv != "undefined") && ((v!==null && v.toString)?v.toString():null) !== lv.toString()){
|
||||
this.undo();
|
||||
dojo.stopEvent(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
forWaiValuenow: function(){
|
||||
// summary: returns a value, reflecting the current state of the widget,
|
||||
// to be used for the ARIA valuenow.
|
||||
// This method may be overridden by subclasses that want
|
||||
// to use something other than this.getValue() for valuenow
|
||||
return this.getValue();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user