require({cache:{
'dijit/_editor/plugins/FontChoice':function(){
define([
"require",
"dojo/_base/array", // array.indexOf array.map
"dojo/_base/declare", // declare
"dojo/dom-construct", // domConstruct.place
"dojo/i18n", // i18n.getLocalization
"dojo/_base/lang", // lang.delegate lang.hitch lang.isString
"dojo/store/Memory", // MemoryStore
"../../registry", // registry.getUniqueId
"../../_Widget",
"../../_TemplatedMixin",
"../../_WidgetsInTemplateMixin",
"../../form/FilteringSelect",
"../_Plugin",
"../range",
"dojo/i18n!../nls/FontChoice"
], function(require, array, declare, domConstruct, i18n, lang, MemoryStore,
registry, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, FilteringSelect, _Plugin, rangeapi){
// module:
// dijit/_editor/plugins/FontChoice
var _FontDropDown = declare("dijit._editor.plugins._FontDropDown",
[_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], {
// summary:
// Base class for widgets that contains a label (like "Font:")
// and a FilteringSelect drop down to pick a value.
// Used as Toolbar entry.
// label: [public] String
// The label to apply to this particular FontDropDown.
label: "",
// plainText: [public] boolean
// Flag to indicate that the returned label should be plain text
// instead of an example.
plainText: false,
// templateString: [public] String
// The template used to construct the labeled dropdown.
templateString: "" +
"" +
"" +
"",
// contextRequire: [public] Function
// The context require that is used to resolve modules in template.
contextRequire: require,
postMixInProperties: function(){
// summary:
// Over-ride to set specific properties.
this.inherited(arguments);
this.strings = i18n.getLocalization("dijit._editor", "FontChoice");
// Set some substitution variables used in the template
this.label = this.strings[this.command];
// _WidgetBase sets the id after postMixInProperties(), but we need it now.
// Alternative is to have a buildRendering() method and move this.selectId setting there,
// or alternately get rid of selectId variable and just access ${id} in template?
this.id = registry.getUniqueId(this.declaredClass.replace(/\./g, "_"));
this.selectId = this.id + "_select"; // used in template
this.inherited(arguments);
},
postCreate: function(){
// summary:
// Over-ride for the default postCreate action
// This establishes the filtering selects and the like.
// Initialize the list of items in the drop down by creating data store with items like:
// {value: 1, name: "xx-small", label: "xx-small" }
this.select.set("store", new MemoryStore({
idProperty: "value",
data: array.map(this.values, function(value){
var name = this.strings[value] || value;
return {
label: this.getLabel(value, name),
name: name,
value: value
};
}, this)
}));
this.select.set("value", "", false);
this.disabled = this.select.get("disabled");
},
_setValueAttr: function(value, priorityChange){
// summary:
// Over-ride for the default action of setting the
// widget value, maps the input to known values
// value: Object|String
// The value to set in the select.
// priorityChange:
// Optional parameter used to tell the select whether or not to fire
// onChange event.
// if the value is not a permitted value, just set empty string to prevent showing the warning icon
priorityChange = priorityChange !== false;
this.select.set('value', array.indexOf(this.values, value) < 0 ? "" : value, priorityChange);
if(!priorityChange){
// Clear the last state in case of updateState calls. Ref: #10466
this.select._lastValueReported = null;
}
},
_getValueAttr: function(){
// summary:
// Allow retrieving the value from the composite select on
// call to button.get("value");
return this.select.get('value');
},
focus: function(){
// summary:
// Over-ride for focus control of this widget. Delegates focus down to the
// filtering select.
this.select.focus();
},
_setDisabledAttr: function(value){
// summary:
// Over-ride for the button's 'disabled' attribute so that it can be
// disabled programmatically.
// Save off ths disabled state so the get retrieves it correctly
//without needing to have a function proxy it.
this._set("disabled", value);
this.select.set("disabled", value);
}
});
var _FontNameDropDown = declare("dijit._editor.plugins._FontNameDropDown", _FontDropDown, {
// summary:
// Dropdown to select a font; goes in editor toolbar.
// generic: [const] Boolean
// Use generic (web standard) font names
generic: false,
// command: [public] String
// The editor 'command' implemented by this plugin.
command: "fontName",
comboClass: "dijitFontNameCombo",
postMixInProperties: function(){
// summary:
// Over-ride for the default posr mixin control
if(!this.values){
this.values = this.generic ?
["serif", "sans-serif", "monospace", "cursive", "fantasy"] : // CSS font-family generics
["Arial", "Times New Roman", "Comic Sans MS", "Courier New"];
}
this.inherited(arguments);
},
getLabel: function(value, name){
// summary:
// Function used to generate the labels of the format dropdown
// will return a formatted, or plain label based on the value
// of the plainText option.
// value: String
// The 'insert value' associated with a name
// name: String
// The text name of the value
if(this.plainText){
return name;
}else{
return "
" + name + "
";
}
},
_setValueAttr: function(value, priorityChange){
// summary:
// Over-ride for the default action of setting the
// widget value, maps the input to known values
priorityChange = priorityChange !== false;
if(this.generic){
var map = {
"Arial": "sans-serif",
"Helvetica": "sans-serif",
"Myriad": "sans-serif",
"Times": "serif",
"Times New Roman": "serif",
"Comic Sans MS": "cursive",
"Apple Chancery": "cursive",
"Courier": "monospace",
"Courier New": "monospace",
"Papyrus": "fantasy",
"Estrangelo Edessa": "cursive", // Windows 7
"Gabriola": "fantasy" // Windows 7
};
value = map[value] || value;
}
this.inherited(arguments, [value, priorityChange]);
}
});
var _FontSizeDropDown = declare("dijit._editor.plugins._FontSizeDropDown", _FontDropDown, {
// summary:
// Dropdown to select a font size; goes in editor toolbar.
// command: [public] String
// The editor 'command' implemented by this plugin.
command: "fontSize",
comboClass: "dijitFontSizeCombo",
// values: [public] Number[]
// The HTML font size values supported by this plugin
values: [1, 2, 3, 4, 5, 6, 7], // sizes according to the old HTML FONT SIZE
getLabel: function(value, name){
// summary:
// Function used to generate the labels of the format dropdown
// will return a formatted, or plain label based on the value
// of the plainText option.
// We're stuck using the deprecated FONT tag to correspond
// with the size measurements used by the editor
// value: String
// The 'insert value' associated with a name
// name: String
// The text name of the value
if(this.plainText){
return name;
}else{
return "" + name + "";
}
},
_setValueAttr: function(value, priorityChange){
// summary:
// Over-ride for the default action of setting the
// widget value, maps the input to known values
priorityChange = priorityChange !== false;
if(value.indexOf && value.indexOf("px") != -1){
var pixels = parseInt(value, 10);
value = {10: 1, 13: 2, 16: 3, 18: 4, 24: 5, 32: 6, 48: 7}[pixels] || value;
}
this.inherited(arguments, [value, priorityChange]);
}
});
var _FormatBlockDropDown = declare("dijit._editor.plugins._FormatBlockDropDown", _FontDropDown, {
// summary:
// Dropdown to select a format (like paragraph or heading); goes in editor toolbar.
// command: [public] String
// The editor 'command' implemented by this plugin.
command: "formatBlock",
comboClass: "dijitFormatBlockCombo",
// values: [public] Array
// The HTML format tags supported by this plugin
values: ["noFormat", "p", "h1", "h2", "h3", "pre"],
postCreate: function(){
// Init and set the default value to no formatting. Update state will adjust it
// as needed.
this.inherited(arguments);
this.set("value", "noFormat", false);
},
getLabel: function(value, name){
// summary:
// Function used to generate the labels of the format dropdown
// will return a formatted, or plain label based on the value
// of the plainText option.
// value: String
// The 'insert value' associated with a name
// name: String
// The text name of the value
if(this.plainText || value == "noFormat"){
return name;
}else{
return "<" + value + ">" + name + "" + value + ">";
}
},
_execCommand: function(editor, command, choice){
// summary:
// Over-ride for default exec-command label.
// Allows us to treat 'none' as special.
if(choice === "noFormat"){
var start;
var end;
var sel = rangeapi.getSelection(editor.window);
if(sel && sel.rangeCount > 0){
var range = sel.getRangeAt(0);
var node, tag;
if(range){
start = range.startContainer;
end = range.endContainer;
// find containing nodes of start/end.
while(start && start !== editor.editNode &&
start !== editor.document.body &&
start.nodeType !== 1){
start = start.parentNode;
}
while(end && end !== editor.editNode &&
end !== editor.document.body &&
end.nodeType !== 1){
end = end.parentNode;
}
var processChildren = lang.hitch(this, function(node, ary){
if(node.childNodes && node.childNodes.length){
var i;
for(i = 0; i < node.childNodes.length; i++){
var c = node.childNodes[i];
if(c.nodeType == 1){
if(editor.selection.inSelection(c)){
var tag = c.tagName ? c.tagName.toLowerCase() : "";
if(array.indexOf(this.values, tag) !== -1){
ary.push(c);
}
processChildren(c, ary);
}
}
}
}
});
var unformatNodes = lang.hitch(this, function(nodes){
// summary:
// Internal function to clear format nodes.
// nodes:
// The array of nodes to strip formatting from.
if(nodes && nodes.length){
editor.beginEditing();
while(nodes.length){
this._removeFormat(editor, nodes.pop());
}
editor.endEditing();
}
});
var clearNodes = [];
if(start == end){
//Contained within the same block, may be collapsed, but who cares, see if we
// have a block element to remove.
var block;
node = start;
while(node && node !== editor.editNode && node !== editor.document.body){
if(node.nodeType == 1){
tag = node.tagName ? node.tagName.toLowerCase() : "";
if(array.indexOf(this.values, tag) !== -1){
block = node;
break;
}
}
node = node.parentNode;
}
//Also look for all child nodes in the selection that may need to be
//cleared of formatting
processChildren(start, clearNodes);
if(block){
clearNodes = [block].concat(clearNodes);
}
unformatNodes(clearNodes);
}else{
// Probably a multi select, so we have to process it. Whee.
node = start;
while(editor.selection.inSelection(node)){
if(node.nodeType == 1){
tag = node.tagName ? node.tagName.toLowerCase() : "";
if(array.indexOf(this.values, tag) !== -1){
clearNodes.push(node);
}
processChildren(node, clearNodes);
}
node = node.nextSibling;
}
unformatNodes(clearNodes);
}
editor.onDisplayChanged();
}
}
}else{
editor.execCommand(command, choice);
}
},
_removeFormat: function(editor, node){
// summary:
// function to remove the block format node.
// node:
// The block format node to remove (and leave the contents behind)
if(editor.customUndo){
// So of course IE doesn't work right with paste-overs.
// We have to do this manually, which is okay since IE already uses
// customUndo and we turned it on for WebKit. WebKit pasted funny,
// so couldn't use the execCommand approach
while(node.firstChild){
domConstruct.place(node.firstChild, node, "before");
}
node.parentNode.removeChild(node);
}else{
// Everyone else works fine this way, a paste-over and is native
// undo friendly.
editor.selection.selectElementChildren(node);
var html = editor.selection.getSelectedHtml();
editor.selection.selectElement(node);
editor.execCommand("inserthtml", html || "");
}
}
});
// TODO: for 2.0, split into FontChoice plugin into three separate classes,
// one for each command (and change registry below)
var FontChoice = declare("dijit._editor.plugins.FontChoice", _Plugin, {
// summary:
// This plugin provides three drop downs for setting style in the editor
// (font, font size, and format block), as controlled by command.
//
// description:
// The commands provided by this plugin are:
//
// - fontName: Provides a drop down to select from a list of font names
// - fontSize: Provides a drop down to select from a list of font sizes
// - formatBlock: Provides a drop down to select from a list of block styles
// which can easily be added to an editor by including one or more of the above commands
// in the `plugins` attribute as follows:
//
// | plugins="['fontName','fontSize',...]"
//
// It is possible to override the default dropdown list by providing an Array for the `custom` property when
// instantiating this plugin, e.g.
//
// | plugins="[{name:'dijit._editor.plugins.FontChoice', command:'fontName', values:['Verdana','Myriad','Garamond']},...]"
//
// Alternatively, for `fontName` only, `generic:true` may be specified to provide a dropdown with
// [CSS generic font families](http://www.w3.org/TR/REC-CSS2/fonts.html#generic-font-families).
//
// Note that the editor is often unable to properly handle font styling information defined outside
// the context of the current editor instance, such as pre-populated HTML.
// useDefaultCommand: [protected] Boolean
// Override _Plugin.useDefaultCommand...
// processing is handled by this plugin, not by dijit/Editor.
useDefaultCommand: false,
_initButton: function(){
// summary:
// Overrides _Plugin._initButton(), to initialize the FilteringSelect+label in toolbar,
// rather than a simple button.
// tags:
// protected
// Create the widget to go into the toolbar (the so-called "button")
var clazz = {
fontName: _FontNameDropDown,
fontSize: _FontSizeDropDown,
formatBlock: _FormatBlockDropDown
}[this.command],
params = this.params;
// For back-compat reasons support setting custom values via "custom" parameter
// rather than "values" parameter. Remove in 2.0.
if(this.params.custom){
params.values = this.params.custom;
}
var editor = this.editor;
this.button = new clazz(lang.delegate({dir: editor.dir, lang: editor.lang}, params));
// Reflect changes to the drop down in the editor
this.own(this.button.select.on("change", lang.hitch(this, function(choice){
// User invoked change, since all internal updates set priorityChange to false and will
// not trigger an onChange event.
if(this.editor.focused){
// put focus back in the iframe, unless focus has somehow been shifted out of the editor completely
this.editor.focus();
}
if(this.command == "fontName" && choice.indexOf(" ") != -1){
choice = "'" + choice + "'";
}
// Invoke, the editor already normalizes commands called through its
// execCommand.
if(this.button._execCommand){
this.button._execCommand(this.editor, this.command, choice);
}else{
this.editor.execCommand(this.command, choice);
}
})));
},
updateState: function(){
// summary:
// Overrides _Plugin.updateState(). This controls updating the menu
// options to the right values on state changes in the document (that trigger a
// test of the actions.)
// It set value of drop down in toolbar to reflect font/font size/format block
// of text at current caret position.
// tags:
// protected
var _e = this.editor;
var _c = this.command;
if(!_e || !_e.isLoaded || !_c.length){
return;
}
if(this.button){
var disabled = this.get("disabled");
this.button.set("disabled", disabled);
if(disabled){
return;
}
var value;
try{
value = _e.queryCommandValue(_c) || "";
}catch(e){
//Firefox may throw error above if the editor is just loaded, ignore it
value = "";
}
// strip off single quotes, if any
var quoted = lang.isString(value) && value.match(/'([^']*)'/);
if(quoted){
value = quoted[1];
}
if(_c === "formatBlock"){
if(!value || value == "p"){
// Some browsers (WebKit) doesn't actually get the tag info right.
// and IE returns paragraph when in a DIV!, so incorrect a lot,
// so we have double-check it.
value = null;
var elem;
// Try to find the current element where the caret is.
var sel = rangeapi.getSelection(this.editor.window);
if(sel && sel.rangeCount > 0){
var range = sel.getRangeAt(0);
if(range){
elem = range.endContainer;
}
}
// Okay, now see if we can find one of the formatting types we're in.
while(elem && elem !== _e.editNode && elem !== _e.document){
var tg = elem.tagName ? elem.tagName.toLowerCase() : "";
if(tg && array.indexOf(this.button.values, tg) > -1){
value = tg;
break;
}
elem = elem.parentNode;
}
if(!value){
// Still no value, so lets select 'none'.
value = "noFormat";
}
}else{
// Check that the block format is one allowed, if not,
// null it so that it gets set to empty.
if(array.indexOf(this.button.values, value) < 0){
value = "noFormat";
}
}
}
if(value !== this.button.get("value")){
// Set the value, but denote it is not a priority change, so no
// onchange fires.
this.button.set('value', value, false);
}
}
}
});
// Register these plugins
array.forEach(["fontName", "fontSize", "formatBlock"], function(name){
_Plugin.registry[name] = function(args){
return new FontChoice({
command: name,
plainText: args.plainText
});
};
});
// Make all classes available through AMD, and return main class
FontChoice._FontDropDown = _FontDropDown;
FontChoice._FontNameDropDown = _FontNameDropDown;
FontChoice._FontSizeDropDown = _FontSizeDropDown;
FontChoice._FormatBlockDropDown = _FormatBlockDropDown;
return FontChoice;
});
},
'dijit/form/TextBox':function(){
define([
"dojo/_base/declare", // declare
"dojo/dom-construct", // domConstruct.create
"dojo/dom-style", // domStyle.getComputedStyle
"dojo/_base/kernel", // kernel.deprecated
"dojo/_base/lang", // lang.hitch
"dojo/on",
"dojo/sniff", // has("ie") has("mozilla")
"./_FormValueWidget",
"./_TextBoxMixin",
"dojo/text!./templates/TextBox.html",
"../main" // to export dijit._setSelectionRange, remove in 2.0
], function(declare, domConstruct, domStyle, kernel, lang, on, has,
_FormValueWidget, _TextBoxMixin, template, dijit){
// module:
// dijit/form/TextBox
var TextBox = declare("dijit.form.TextBox" + (has("dojo-bidi") ? "_NoBidi" : ""), [_FormValueWidget, _TextBoxMixin], {
// summary:
// A base class for textbox form inputs
templateString: template,
_singleNodeTemplate: '',
_buttonInputDisabled: has("ie") ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events
baseClass: "dijitTextBox",
postMixInProperties: function(){
var type = this.type.toLowerCase();
if(this.templateString && this.templateString.toLowerCase() == "input" || ((type == "hidden" || type == "file") && this.templateString == this.constructor.prototype.templateString)){
this.templateString = this._singleNodeTemplate;
}
this.inherited(arguments);
},
postCreate: function(){
this.inherited(arguments);
if(has("ie") < 9){
// IE INPUT tag fontFamily has to be set directly using STYLE
// the defer gives IE a chance to render the TextBox and to deal with font inheritance
this.defer(function(){
try{
var s = domStyle.getComputedStyle(this.domNode); // can throw an exception if widget is immediately destroyed
if(s){
var ff = s.fontFamily;
if(ff){
var inputs = this.domNode.getElementsByTagName("INPUT");
if(inputs){
for(var i=0; i < inputs.length; i++){
inputs[i].style.fontFamily = ff;
}
}
}
}
}catch(e){/*when used in a Dialog, and this is called before the dialog is
shown, s.fontFamily would trigger "Invalid Argument" error.*/}
});
}
},
_setPlaceHolderAttr: function(v){
this._set("placeHolder", v);
if(!this._phspan){
this._attachPoints.push('_phspan');
// dijitInputField class gives placeHolder same padding as the input field
// parent node already has dijitInputField class but it doesn't affect this
// since it's position: absolute.
this._phspan = domConstruct.create('span',{ onmousedown:function(e){ e.preventDefault(); }, className:'dijitPlaceHolder dijitInputField'},this.textbox,'after');
this.own(on(this._phspan, "touchend, MSPointerUp", lang.hitch(this, function(){
// If the user clicks placeholder rather than the , need programmatic focus. Normally this
// is done in _FormWidgetMixin._onFocus() but after [30663] it's done on a delay, which is ineffective.
this.focus();
})));
}
this._phspan.innerHTML="";
this._phspan.appendChild(this._phspan.ownerDocument.createTextNode(v));
this._updatePlaceHolder();
},
_onInput: function(/*Event*/ evt){
// summary:
// Called AFTER the input event has happened
// See if the placeHolder text should be removed or added while editing.
this.inherited(arguments);
this._updatePlaceHolder();
},
_updatePlaceHolder: function(){
if(this._phspan){
this._phspan.style.display = (this.placeHolder && !this.textbox.value) ? "" : "none";
}
},
_setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
this.inherited(arguments);
this._updatePlaceHolder();
},
getDisplayedValue: function(){
// summary:
// Deprecated. Use get('displayedValue') instead.
// tags:
// deprecated
kernel.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use get('displayedValue') instead.", "", "2.0");
return this.get('displayedValue');
},
setDisplayedValue: function(/*String*/ value){
// summary:
// Deprecated. Use set('displayedValue', ...) instead.
// tags:
// deprecated
kernel.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use set('displayedValue', ...) instead.", "", "2.0");
this.set('displayedValue', value);
},
_onBlur: function(e){
if(this.disabled){ return; }
this.inherited(arguments);
this._updatePlaceHolder();
if(has("mozilla")){
if(this.selectOnClick){
// clear selection so that the next mouse click doesn't reselect
this.textbox.selectionStart = this.textbox.selectionEnd = undefined;
}
}
},
_onFocus: function(/*String*/ by){
if(this.disabled || this.readOnly){ return; }
this.inherited(arguments);
this._updatePlaceHolder();
}
});
if(has("ie")){
TextBox.prototype._isTextSelected = function(){
var range = this.ownerDocument.selection.createRange();
var parent = range.parentElement();
return parent == this.textbox && range.text.length > 0;
};
// Overrides definition of _setSelectionRange from _TextBoxMixin (TODO: move to _TextBoxMixin.js?)
dijit._setSelectionRange = _TextBoxMixin._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
if(element.createTextRange){
var r = element.createTextRange();
r.collapse(true);
r.moveStart("character", -99999); // move to 0
r.moveStart("character", start); // delta from 0 is the correct position
r.moveEnd("character", stop-start);
r.select();
}
}
}
if(has("dojo-bidi")){
TextBox = declare("dijit.form.TextBox", TextBox, {
_setPlaceHolderAttr: function(v){
this.inherited(arguments);
this.applyTextDir(this._phspan);
}
});
}
return TextBox;
});
},
'dojo/currency':function(){
define([
"./_base/array",
"./_base/lang",
/*===== "./_base/declare", =====*/
"./number",
"./i18n", "./i18n!./cldr/nls/currency",
"./cldr/monetary"
], function(darray, lang, /*===== declare, =====*/ dnumber, i18n, nlsCurrency, cldrMonetary){
// module:
// dojo/currency
var currency = {
// summary:
// localized formatting and parsing routines for currencies
// description:
// extends dojo.number to provide culturally-appropriate formatting of values
// in various world currencies, including use of a currency symbol. The currencies are specified
// by a three-letter international symbol in all uppercase, and support for the currencies is
// provided by the data in `dojo.cldr`. The scripts generating dojo.cldr specify which
// currency support is included. A fixed number of decimal places is determined based
// on the currency type and is not determined by the 'pattern' argument. The fractional
// portion is optional, by default, and variable length decimals are not supported.
};
lang.setObject("dojo.currency", currency);
currency._mixInDefaults = function(options){
options = options || {};
options.type = "currency";
// Get locale-dependent currency data, like the symbol
var bundle = i18n.getLocalization("dojo.cldr", "currency", options.locale) || {};
// Mixin locale-independent currency data, like # of places
var iso = options.currency;
var data = cldrMonetary.getData(iso);
darray.forEach(["displayName","symbol","group","decimal"], function(prop){
data[prop] = bundle[iso+"_"+prop];
});
data.fractional = [true, false];
// Mixin with provided options
return lang.mixin(data, options);
};
/*=====
currency.__FormatOptions = declare([dnumber.__FormatOptions], {
// type: String?
// Should not be set. Value is assumed to be "currency".
// symbol: String?
// localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
// A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
// currency: String?
// an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
// For use with dojo.currency only.
// places: Number?
// number of decimal places to show. Default is defined based on which currency is used.
type: "",
symbol: "",
currency: "",
places: ""
});
=====*/
currency.format = function(/*Number*/ value, /*__FormatOptions?*/ options){
// summary:
// Format a Number as a currency, using locale-specific settings
//
// description:
// Create a string from a Number using a known, localized pattern.
// [Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Elements)
// appropriate to the locale are chosen from the [CLDR](http://unicode.org/cldr)
// as well as the appropriate symbols and delimiters and number of decimal places.
//
// value:
// the number to be formatted.
return dnumber.format(value, currency._mixInDefaults(options));
};
currency.regexp = function(/*dnumber.__RegexpOptions?*/ options){
//
// summary:
// Builds the regular needed to parse a currency value
//
// description:
// Returns regular expression with positive and negative match, group and decimal separators
// Note: the options.places default, the number of decimal places to accept, is defined by the currency type.
return dnumber.regexp(currency._mixInDefaults(options)); // String
};
/*=====
var __ParseOptions = currency.__ParseOptions = declare(dnumber.__ParseOptions, {
// type: String?
// Should not be set. Value is assumed to be currency.
// currency: String?
// an [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code, a three letter sequence like "USD".
// For use with dojo.currency only.
// symbol: String?
// localized currency symbol. The default will be looked up in table of supported currencies in `dojo.cldr`
// A [ISO4217](http://en.wikipedia.org/wiki/ISO_4217) currency code will be used if not found.
// places: Number?
// fixed number of decimal places to accept. The default is determined based on which currency is used.
// fractional: Boolean|Array?
// Whether to include the fractional portion, where the number of decimal places are implied by the currency
// or explicit 'places' parameter. The value [true,false] makes the fractional portion optional.
// By default for currencies, it the fractional portion is optional.
});
=====*/
currency.parse = function(/*String*/ expression, /*__ParseOptions?*/ options){
//
// summary:
// Convert a properly formatted currency string to a primitive Number,
// using locale-specific settings.
// description:
// Create a Number from a string using a known, localized pattern.
// [Formatting patterns](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
// are chosen appropriate to the locale, as well as the appropriate symbols and delimiters
// and number of decimal places.
// expression:
// A string representation of a currency value
return dnumber.parse(expression, currency._mixInDefaults(options));
};
return currency;
});
},
'dijit/layout/ScrollingTabController':function(){
define([
"dojo/_base/array", // array.forEach
"dojo/_base/declare", // declare
"dojo/dom-class", // domClass.add domClass.contains
"dojo/dom-geometry", // domGeometry.contentBox
"dojo/dom-style", // domStyle.style
"dojo/_base/fx", // Animation
"dojo/_base/lang", // lang.hitch
"dojo/on",
"dojo/query", // query
"dojo/sniff", // has("ie"), has("webkit"), has("quirks")
"../registry", // registry.byId()
"dojo/text!./templates/ScrollingTabController.html",
"dojo/text!./templates/_ScrollingTabControllerButton.html",
"./TabController",
"./utils", // marginBox2contextBox, layoutChildren
"../_WidgetsInTemplateMixin",
"../Menu",
"../MenuItem",
"../form/Button",
"../_HasDropDown",
"dojo/NodeList-dom", // NodeList.style
"../a11yclick" // template uses ondijitclick (not for keyboard support, but for responsive touch support)
], function(array, declare, domClass, domGeometry, domStyle, fx, lang, on, query, has,
registry, tabControllerTemplate, buttonTemplate, TabController, layoutUtils, _WidgetsInTemplateMixin,
Menu, MenuItem, Button, _HasDropDown){
// module:
// dijit/layout/ScrollingTabController
var ScrollingTabController = declare("dijit.layout.ScrollingTabController", [TabController, _WidgetsInTemplateMixin], {
// summary:
// Set of tabs with left/right arrow keys and a menu to switch between tabs not
// all fitting on a single row.
// Works only for horizontal tabs (either above or below the content, not to the left
// or right).
// tags:
// private
baseClass: "dijitTabController dijitScrollingTabController",
templateString: tabControllerTemplate,
// useMenu: [const] Boolean
// True if a menu should be used to select tabs when they are too
// wide to fit the TabContainer, false otherwise.
useMenu: true,
// useSlider: [const] Boolean
// True if a slider should be used to select tabs when they are too
// wide to fit the TabContainer, false otherwise.
useSlider: true,
// tabStripClass: [const] String
// The css class to apply to the tab strip, if it is visible.
tabStripClass: "",
// _minScroll: Number
// The distance in pixels from the edge of the tab strip which,
// if a scroll animation is less than, forces the scroll to
// go all the way to the left/right.
_minScroll: 5,
// Override default behavior mapping class to DOMNode
_setClassAttr: { node: "containerNode", type: "class" },
buildRendering: function(){
this.inherited(arguments);
var n = this.domNode;
this.scrollNode = this.tablistWrapper;
this._initButtons();
if(!this.tabStripClass){
this.tabStripClass = "dijitTabContainer" +
this.tabPosition.charAt(0).toUpperCase() +
this.tabPosition.substr(1).replace(/-.*/, "") +
"None";
domClass.add(n, "tabStrip-disabled")
}
domClass.add(this.tablistWrapper, this.tabStripClass);
},
onStartup: function(){
this.inherited(arguments);
// TabController is hidden until it finishes drawing, to give
// a less visually jumpy instantiation. When it's finished, set visibility to ""
// to that the tabs are hidden/shown depending on the container's visibility setting.
domStyle.set(this.domNode, "visibility", "");
this._postStartup = true;
// changes to the tab button label or iconClass will have changed the width of the
// buttons, so do a resize
this.own(on(this.containerNode, "attrmodified-label, attrmodified-iconclass", lang.hitch(this, function(evt){
if(this._dim){
this.resize(this._dim);
}
})));
},
onAddChild: function(page, insertIndex){
this.inherited(arguments);
// Increment the width of the wrapper when a tab is added
// This makes sure that the buttons never wrap.
// The value 200 is chosen as it should be bigger than most
// Tab button widths.
domStyle.set(this.containerNode, "width",
(domStyle.get(this.containerNode, "width") + 200) + "px");
},
onRemoveChild: function(page, insertIndex){
// null out _selectedTab because we are about to delete that dom node
var button = this.pane2button(page.id);
if(this._selectedTab === button.domNode){
this._selectedTab = null;
}
this.inherited(arguments);
},
_initButtons: function(){
// summary:
// Creates the buttons used to scroll to view tabs that
// may not be visible if the TabContainer is too narrow.
// Make a list of the buttons to display when the tab labels become
// wider than the TabContainer, and hide the other buttons.
// Also gets the total width of the displayed buttons.
this._btnWidth = 0;
this._buttons = query("> .tabStripButton", this.domNode).filter(function(btn){
if((this.useMenu && btn == this._menuBtn.domNode) ||
(this.useSlider && (btn == this._rightBtn.domNode || btn == this._leftBtn.domNode))){
this._btnWidth += domGeometry.getMarginSize(btn).w;
return true;
}else{
domStyle.set(btn, "display", "none");
return false;
}
}, this);
},
_getTabsWidth: function(){
var children = this.getChildren();
if(children.length){
var leftTab = children[this.isLeftToRight() ? 0 : children.length - 1].domNode,
rightTab = children[this.isLeftToRight() ? children.length - 1 : 0].domNode;
return rightTab.offsetLeft + rightTab.offsetWidth - leftTab.offsetLeft;
}else{
return 0;
}
},
_enableBtn: function(width){
// summary:
// Determines if the tabs are wider than the width of the TabContainer, and
// thus that we need to display left/right/menu navigation buttons.
var tabsWidth = this._getTabsWidth();
width = width || domStyle.get(this.scrollNode, "width");
return tabsWidth > 0 && width < tabsWidth;
},
resize: function(dim){
// summary:
// Hides or displays the buttons used to scroll the tab list and launch the menu
// that selects tabs.
// Save the dimensions to be used when a child is renamed.
this._dim = dim;
// Set my height to be my natural height (tall enough for one row of tab labels),
// and my content-box width based on margin-box width specified in dim parameter.
// But first reset scrollNode.height in case it was set by layoutChildren() call
// in a previous run of this method.
this.scrollNode.style.height = "auto";
var cb = this._contentBox = layoutUtils.marginBox2contentBox(this.domNode, {h: 0, w: dim.w});
cb.h = this.scrollNode.offsetHeight;
domGeometry.setContentSize(this.domNode, cb);
// Show/hide the left/right/menu navigation buttons depending on whether or not they
// are needed.
var enable = this._enableBtn(this._contentBox.w);
this._buttons.style("display", enable ? "" : "none");
// Position and size the navigation buttons and the tablist
this._leftBtn.region = "left";
this._rightBtn.region = "right";
this._menuBtn.region = this.isLeftToRight() ? "right" : "left";
layoutUtils.layoutChildren(this.domNode, this._contentBox,
[this._menuBtn, this._leftBtn, this._rightBtn, {domNode: this.scrollNode, region: "center"}]);
// set proper scroll so that selected tab is visible
if(this._selectedTab){
if(this._anim && this._anim.status() == "playing"){
this._anim.stop();
}
this.scrollNode.scrollLeft = this._convertToScrollLeft(this._getScrollForSelectedTab());
}
// Enable/disabled left right buttons depending on whether or not user can scroll to left or right
this._setButtonClass(this._getScroll());
this._postResize = true;
// Return my size so layoutChildren() can use it.
// Also avoids IE9 layout glitch on browser resize when scroll buttons present
return {h: this._contentBox.h, w: dim.w};
},
_getScroll: function(){
// summary:
// Returns the current scroll of the tabs where 0 means
// "scrolled all the way to the left" and some positive number, based on #
// of pixels of possible scroll (ex: 1000) means "scrolled all the way to the right"
return (this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")) ? this.scrollNode.scrollLeft :
domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width")
+ (has("ie") >= 8 ? -1 : 1) * this.scrollNode.scrollLeft;
},
_convertToScrollLeft: function(val){
// summary:
// Given a scroll value where 0 means "scrolled all the way to the left"
// and some positive number, based on # of pixels of possible scroll (ex: 1000)
// means "scrolled all the way to the right", return value to set this.scrollNode.scrollLeft
// to achieve that scroll.
//
// This method is to adjust for RTL funniness in various browsers and versions.
if(this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")){
return val;
}else{
var maxScroll = domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width");
return (has("ie") >= 8 ? -1 : 1) * (val - maxScroll);
}
},
onSelectChild: function(/*dijit/_WidgetBase*/ page){
// summary:
// Smoothly scrolls to a tab when it is selected.
var tab = this.pane2button(page.id);
if(!tab){
return;
}
var node = tab.domNode;
// Save the selection
if(node != this._selectedTab){
this._selectedTab = node;
// Scroll to the selected tab, except on startup, when scrolling is handled in resize()
if(this._postResize){
var sl = this._getScroll();
if(sl > node.offsetLeft ||
sl + domStyle.get(this.scrollNode, "width") <
node.offsetLeft + domStyle.get(node, "width")){
this.createSmoothScroll().play();
}
}
}
this.inherited(arguments);
},
_getScrollBounds: function(){
// summary:
// Returns the minimum and maximum scroll setting to show the leftmost and rightmost
// tabs (respectively)
var children = this.getChildren(),
scrollNodeWidth = domStyle.get(this.scrollNode, "width"), // about 500px
containerWidth = domStyle.get(this.containerNode, "width"), // 50,000px
maxPossibleScroll = containerWidth - scrollNodeWidth, // scrolling until right edge of containerNode visible
tabsWidth = this._getTabsWidth();
if(children.length && tabsWidth > scrollNodeWidth){
// Scrolling should happen
return {
min: this.isLeftToRight() ? 0 : children[children.length - 1].domNode.offsetLeft,
max: this.isLeftToRight() ?
(children[children.length - 1].domNode.offsetLeft + children[children.length - 1].domNode.offsetWidth) - scrollNodeWidth :
maxPossibleScroll
};
}else{
// No scrolling needed, all tabs visible, we stay either scrolled to far left or far right (depending on dir)
var onlyScrollPosition = this.isLeftToRight() ? 0 : maxPossibleScroll;
return {
min: onlyScrollPosition,
max: onlyScrollPosition
};
}
},
_getScrollForSelectedTab: function(){
// summary:
// Returns the scroll value setting so that the selected tab
// will appear in the center
var w = this.scrollNode,
n = this._selectedTab,
scrollNodeWidth = domStyle.get(this.scrollNode, "width"),
scrollBounds = this._getScrollBounds();
// TODO: scroll minimal amount (to either right or left) so that
// selected tab is fully visible, and just return if it's already visible?
var pos = (n.offsetLeft + domStyle.get(n, "width") / 2) - scrollNodeWidth / 2;
pos = Math.min(Math.max(pos, scrollBounds.min), scrollBounds.max);
// TODO:
// If scrolling close to the left side or right side, scroll
// all the way to the left or right. See this._minScroll.
// (But need to make sure that doesn't scroll the tab out of view...)
return pos;
},
createSmoothScroll: function(x){
// summary:
// Creates a dojo._Animation object that smoothly scrolls the tab list
// either to a fixed horizontal pixel value, or to the selected tab.
// description:
// If an number argument is passed to the function, that horizontal
// pixel position is scrolled to. Otherwise the currently selected
// tab is scrolled to.
// x: Integer?
// An optional pixel value to scroll to, indicating distance from left.
// Calculate position to scroll to
if(arguments.length > 0){
// position specified by caller, just make sure it's within bounds
var scrollBounds = this._getScrollBounds();
x = Math.min(Math.max(x, scrollBounds.min), scrollBounds.max);
}else{
// scroll to center the current tab
x = this._getScrollForSelectedTab();
}
if(this._anim && this._anim.status() == "playing"){
this._anim.stop();
}
var self = this,
w = this.scrollNode,
anim = new fx.Animation({
beforeBegin: function(){
if(this.curve){
delete this.curve;
}
var oldS = w.scrollLeft,
newS = self._convertToScrollLeft(x);
anim.curve = new fx._Line(oldS, newS);
},
onAnimate: function(val){
w.scrollLeft = val;
}
});
this._anim = anim;
// Disable/enable left/right buttons according to new scroll position
this._setButtonClass(x);
return anim; // dojo/_base/fx/Animation
},
_getBtnNode: function(/*Event*/ e){
// summary:
// Gets a button DOM node from a mouse click event.
// e:
// The mouse click event.
var n = e.target;
while(n && !domClass.contains(n, "tabStripButton")){
n = n.parentNode;
}
return n;
},
doSlideRight: function(/*Event*/ e){
// summary:
// Scrolls the menu to the right.
// e:
// The mouse click event.
this.doSlide(1, this._getBtnNode(e));
},
doSlideLeft: function(/*Event*/ e){
// summary:
// Scrolls the menu to the left.
// e:
// The mouse click event.
this.doSlide(-1, this._getBtnNode(e));
},
doSlide: function(/*Number*/ direction, /*DomNode*/ node){
// summary:
// Scrolls the tab list to the left or right by 75% of the widget width.
// direction:
// If the direction is 1, the widget scrolls to the right, if it is -1,
// it scrolls to the left.
if(node && domClass.contains(node, "dijitTabDisabled")){
return;
}
var sWidth = domStyle.get(this.scrollNode, "width");
var d = (sWidth * 0.75) * direction;
var to = this._getScroll() + d;
this._setButtonClass(to);
this.createSmoothScroll(to).play();
},
_setButtonClass: function(/*Number*/ scroll){
// summary:
// Disables the left scroll button if the tabs are scrolled all the way to the left,
// or the right scroll button in the opposite case.
// scroll: Integer
// amount of horizontal scroll
var scrollBounds = this._getScrollBounds();
this._leftBtn.set("disabled", scroll <= scrollBounds.min);
this._rightBtn.set("disabled", scroll >= scrollBounds.max);
}
});
var ScrollingTabControllerButtonMixin = declare("dijit.layout._ScrollingTabControllerButtonMixin", null, {
baseClass: "dijitTab tabStripButton",
templateString: buttonTemplate,
// Override inherited tabIndex: 0 from dijit/form/Button, because user shouldn't be
// able to tab to the left/right/menu buttons
tabIndex: "",
// Similarly, override FormWidget.isFocusable() because clicking a button shouldn't focus it
// either (this override avoids focus() call in FormWidget.js)
isFocusable: function(){
return false;
}
});
// Class used in template
declare("dijit.layout._ScrollingTabControllerButton", [Button, ScrollingTabControllerButtonMixin]);
// Class used in template
declare("dijit.layout._ScrollingTabControllerMenuButton", [Button, _HasDropDown, ScrollingTabControllerButtonMixin], {
// id of the TabContainer itself
containerId: "",
// -1 so user can't tab into the button, but so that button can still be focused programatically.
// Because need to move focus to the button (or somewhere) before the menu is hidden or IE6 will crash.
tabIndex: "-1",
isLoaded: function(){
// recreate menu every time, in case the TabContainer's list of children (or their icons/labels) have changed
return false;
},
loadDropDown: function(callback){
this.dropDown = new Menu({
id: this.containerId + "_menu",
ownerDocument: this.ownerDocument,
dir: this.dir,
lang: this.lang,
textDir: this.textDir
});
var container = registry.byId(this.containerId);
array.forEach(container.getChildren(), function(page){
var menuItem = new MenuItem({
id: page.id + "_stcMi",
label: page.title,
iconClass: page.iconClass,
disabled: page.disabled,
ownerDocument: this.ownerDocument,
dir: page.dir,
lang: page.lang,
textDir: page.textDir || container.textDir,
onClick: function(){
container.selectChild(page);
}
});
this.dropDown.addChild(menuItem);
}, this);
callback();
},
closeDropDown: function(/*Boolean*/ focus){
this.inherited(arguments);
if(this.dropDown){
this._popupStateNode.removeAttribute("aria-owns"); // remove ref to node that we are about to delete
this.dropDown.destroyRecursive();
delete this.dropDown;
}
}
});
return ScrollingTabController;
});
},
'dijit/DialogUnderlay':function(){
define([
"dojo/_base/declare", // declare
"dojo/_base/lang", // lang.hitch
"dojo/aspect", // aspect.after
"dojo/dom-attr", // domAttr.set
"dojo/dom-style", // domStyle.getComputedStyle
"dojo/on",
"dojo/window", // winUtils.getBox, winUtils.get
"./_Widget",
"./_TemplatedMixin",
"./BackgroundIframe",
"./Viewport",
"./main" // for back-compat, exporting dijit._underlay (remove in 2.0)
], function(declare, lang, aspect, domAttr, domStyle, on,
winUtils, _Widget, _TemplatedMixin, BackgroundIframe, Viewport, dijit){
// module:
// dijit/DialogUnderlay
var DialogUnderlay = declare("dijit.DialogUnderlay", [_Widget, _TemplatedMixin], {
// summary:
// A component used to block input behind a `dijit/Dialog`.
//
// Normally this class should not be instantiated directly, but rather shown and hidden via
// DialogUnderlay.show() and DialogUnderlay.hide(). And usually the module is not accessed directly
// at all, since the underlay is shown and hidden by Dialog.DialogLevelManager.
//
// The underlay itself can be styled based on and id:
// | #myDialog_underlay { background-color:red; }
//
// In the case of `dijit.Dialog`, this id is based on the id of the Dialog,
// suffixed with _underlay.
// 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: "
",
// Parameters on creation or updatable later
// dialogId: String
// Id of the dialog.... DialogUnderlay's id is based on this id
dialogId: "",
// class: String
// This class name is used on the DialogUnderlay node, in addition to dijitDialogUnderlay
"class": "",
// This will get overwritten as soon as show() is call, but leave an empty array in case hide() or destroy()
// is called first. The array is shared between instances but that's OK because we never write into it.
_modalConnects: [],
_setDialogIdAttr: function(id){
domAttr.set(this.node, "id", id + "_underlay");
this._set("dialogId", id);
},
_setClassAttr: function(clazz){
this.node.className = "dijitDialogUnderlay " + clazz;
this._set("class", clazz);
},
postCreate: function(){
// Append the underlay to the body
this.ownerDocumentBody.appendChild(this.domNode);
this.own(on(this.domNode, "keydown", lang.hitch(this, "_onKeyDown")));
this.inherited(arguments);
},
layout: function(){
// summary:
// Sets the background to the size of the viewport
//
// description:
// 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.
// tags:
// private
var is = this.node.style,
os = this.domNode.style;
// hide the background temporarily, so that the background itself isn't
// causing scrollbars to appear (might happen when user shrinks browser
// window and then we are called to resize)
os.display = "none";
// then resize and show
var viewport = winUtils.getBox(this.ownerDocument);
os.top = viewport.t + "px";
os.left = viewport.l + "px";
is.width = viewport.w + "px";
is.height = viewport.h + "px";
os.display = "block";
},
show: function(){
// summary:
// Show the dialog underlay
this.domNode.style.display = "block";
this.open = true;
this.layout();
this.bgIframe = new BackgroundIframe(this.domNode);
var win = winUtils.get(this.ownerDocument);
this._modalConnects = [
Viewport.on("resize", lang.hitch(this, "layout")),
on(win, "scroll", lang.hitch(this, "layout"))
];
},
hide: function(){
// summary:
// Hides the dialog underlay
this.bgIframe.destroy();
delete this.bgIframe;
this.domNode.style.display = "none";
while(this._modalConnects.length){ (this._modalConnects.pop()).remove(); }
this.open = false;
},
destroy: function(){
while(this._modalConnects.length){ (this._modalConnects.pop()).remove(); }
this.inherited(arguments);
},
_onKeyDown: function(){
// summary:
// Extension point so Dialog can monitor keyboard events on the underlay.
}
});
DialogUnderlay.show = function(/*Object*/ attrs, /*Number*/ zIndex){
// summary:
// Display the underlay with the given attributes set. If the underlay is already displayed,
// then adjust it's attributes as specified.
// attrs:
// The parameters to create DialogUnderlay with.
// zIndex:
// zIndex of the underlay
var underlay = DialogUnderlay._singleton;
if(!underlay || underlay._destroyed){
underlay = dijit._underlay = DialogUnderlay._singleton = new DialogUnderlay(attrs);
}else{
if(attrs){ underlay.set(attrs); }
}
domStyle.set(underlay.domNode, 'zIndex', zIndex);
if(!underlay.open){
underlay.show();
}
};
DialogUnderlay.hide = function(){
// summary:
// Hide the underlay.
// Guard code in case the underlay widget has already been destroyed
// because we are being called during page unload (when all widgets are destroyed)
var underlay = DialogUnderlay._singleton;
if(underlay && !underlay._destroyed){
underlay.hide();
}
};
return DialogUnderlay;
});
},
'dijit/_editor/html':function(){
define([
"dojo/_base/array",
"dojo/_base/lang", // lang.setObject
"dojo/sniff" // has("ie")
], function(array, lang, has){
// module:
// dijit/_editor/html
var exports = {
// summary:
// HTML serialization utility functions used by editor
};
lang.setObject("dijit._editor.html", exports);
var escape = exports.escapeXml = function(/*String*/ str, /*Boolean?*/ noSingleQuotes){
// summary:
// Adds escape sequences for special characters in XML: `&<>"'`.
// Optionally skips escapes for single quotes.
str = str.replace(/&/gm, "&").replace(//gm, ">").replace(/"/gm, """);
if(!noSingleQuotes){
str = str.replace(/'/gm, "'");
}
return str; // string
};
exports.getNodeHtml = function(/*DomNode*/ node){
// summary:
// Return string representing HTML for node and it's children
var output = [];
exports.getNodeHtmlHelper(node, output);
return output.join("");
};
exports.getNodeHtmlHelper = function(/*DomNode*/ node, /*String[]*/ output){
// summary:
// Pushes array of strings into output[] which represent HTML for node and it's children
switch(node.nodeType){
case 1: // element node
var lName = node.nodeName.toLowerCase();
if(!lName || lName.charAt(0) == "/"){
// IE does some strange things with malformed HTML input, like
// treating a close tag without an open tag , as
// a new tag with tagName of /span. Corrupts output HTML, remove
// them. Other browsers don't prefix tags that way, so will
// never show up.
return "";
}
output.push('<', lName);
// store the list of attributes and sort it to have the
// attributes appear in the dictionary order
var attrarray = [], attrhash = {};
var attr;
if(has("dom-attributes-explicit") || has("dom-attributes-specified-flag")){
// IE8+ and all other browsers.
var i = 0;
while((attr = node.attributes[i++])){
// ignore all attributes starting with _dj which are
// internal temporary attributes used by the editor
var n = attr.name;
if(n.substr(0, 3) !== '_dj' &&
(!has("dom-attributes-specified-flag") || attr.specified) && !(n in attrhash)){ // workaround repeated attributes bug in IE8 (LinkDialog test)
var v = attr.value;
if(n == 'src' || n == 'href'){
if(node.getAttribute('_djrealurl')){
v = node.getAttribute('_djrealurl');
}
}
if(has("ie") === 8 && n === "style"){
v = v.replace("HEIGHT:", "height:").replace("WIDTH:", "width:");
}
attrarray.push([n, v]);
attrhash[n] = v;
}
}
}else{
// IE6-7 code path
var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false);
var s = clone.outerHTML;
// Split up and manage the attrs via regexp
// similar to prettyPrint attr logic.
var rgxp_attrsMatch = /[\w-]+=("[^"]*"|'[^']*'|\S*)/gi
var attrSplit = s.match(rgxp_attrsMatch);
s = s.substr(0, s.indexOf('>'));
array.forEach(attrSplit, function(attr){
if(attr){
var idx = attr.indexOf("=");
if(idx > 0){
var key = attr.substring(0, idx);
if(key.substr(0, 3) != '_dj'){
if(key == 'src' || key == 'href'){
if(node.getAttribute('_djrealurl')){
attrarray.push([key, node.getAttribute('_djrealurl')]);
return;
}
}
var val, match;
switch(key){
case 'style':
val = node.style.cssText.toLowerCase();
break;
case 'class':
val = node.className;
break;
case 'width':
if(lName === "img"){
// This somehow gets lost on IE for IMG tags and the like
// and we have to find it in outerHTML, known IE oddity.
match = /width=(\S+)/i.exec(s);
if(match){
val = match[1];
}
break;
}
case 'height':
if(lName === "img"){
// This somehow gets lost on IE for IMG tags and the like
// and we have to find it in outerHTML, known IE oddity.
match = /height=(\S+)/i.exec(s);
if(match){
val = match[1];
}
break;
}
default:
val = node.getAttribute(key);
}
if(val != null){
attrarray.push([key, val.toString()]);
}
}
}
}
}, this);
}
attrarray.sort(function(a, b){
return a[0] < b[0] ? -1 : (a[0] == b[0] ? 0 : 1);
});
var j = 0;
while((attr = attrarray[j++])){
output.push(' ', attr[0], '="',
(typeof attr[1] === "string" ? escape(attr[1], true) : attr[1]), '"');
}
switch(lName){
case 'br':
case 'hr':
case 'img':
case 'input':
case 'base':
case 'meta':
case 'area':
case 'basefont':
// These should all be singly closed
output.push(' />');
break;
case 'script':
// Browsers handle script tags differently in how you get content,
// but innerHTML always seems to work, so insert its content that way
// Yes, it's bad to allow script tags in the editor code, but some people
// seem to want to do it, so we need to at least return them right.
// other plugins/filters can strip them.
output.push('>', node.innerHTML, '', lName, '>');
break;
default:
output.push('>');
if(node.hasChildNodes()){
exports.getChildrenHtmlHelper(node, output);
}
output.push('', lName, '>');
}
break;
case 4: // cdata
case 3: // text
// FIXME:
output.push(escape(node.nodeValue, true));
break;
case 8: // comment
// FIXME:
output.push('');
break;
default:
output.push("");
}
};
exports.getChildrenHtml = function(/*DomNode*/ node){
// summary:
// Returns the html content of a DomNode's children
var output = [];
exports.getChildrenHtmlHelper(node, output);
return output.join("");
};
exports.getChildrenHtmlHelper = function(/*DomNode*/ dom, /*String[]*/ output){
// summary:
// Pushes the html content of a DomNode's children into out[]
if(!dom){
return;
}
var nodes = dom["childNodes"] || dom;
// IE issue.
// If we have an actual node we can check parent relationships on for IE,
// We should check, as IE sometimes builds invalid DOMS. If no parent, we can't check
// And should just process it and hope for the best.
var checkParent = !has("ie") || nodes !== dom;
var node, i = 0;
while((node = nodes[i++])){
// IE is broken. DOMs are supposed to be a tree. But in the case of malformed HTML, IE generates a graph
// meaning one node ends up with multiple references (multiple parents). This is totally wrong and invalid, but
// such is what it is. We have to keep track and check for this because otherwise the source output HTML will have dups.
// No other browser generates a graph. Leave it to IE to break a fundamental DOM rule. So, we check the parent if we can
// If we can't, nothing more we can do other than walk it.
if(!checkParent || node.parentNode == dom){
exports.getNodeHtmlHelper(node, output);
}
}
};
return exports;
});
},
'dijit/_HasDropDown':function(){
define([
"dojo/_base/declare", // declare
"dojo/_base/Deferred",
"dojo/dom", // dom.isDescendant
"dojo/dom-attr", // domAttr.set
"dojo/dom-class", // domClass.add domClass.contains domClass.remove
"dojo/dom-geometry", // domGeometry.marginBox domGeometry.position
"dojo/dom-style", // domStyle.set
"dojo/has", // has("touch")
"dojo/keys", // keys.DOWN_ARROW keys.ENTER keys.ESCAPE
"dojo/_base/lang", // lang.hitch lang.isFunction
"dojo/on",
"dojo/touch",
"./registry", // registry.byNode()
"./focus",
"./popup",
"./_FocusMixin"
], function(declare, Deferred, dom, domAttr, domClass, domGeometry, domStyle, has, keys, lang, on, touch,
registry, focus, popup, _FocusMixin){
// module:
// dijit/_HasDropDown
return declare("dijit._HasDropDown", _FocusMixin, {
// summary:
// Mixin for widgets that need drop down ability.
// _buttonNode: [protected] DomNode
// The button/icon/node to click to display the drop down.
// Can be set via a data-dojo-attach-point assignment.
// If missing, then either focusNode or domNode (if focusNode is also missing) will be used.
_buttonNode: null,
// _arrowWrapperNode: [protected] DomNode
// Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending
// on where the drop down is set to be positioned.
// Can be set via a data-dojo-attach-point assignment.
// If missing, then _buttonNode will be used.
_arrowWrapperNode: null,
// _popupStateNode: [protected] DomNode
// The node to set the aria-expanded class on.
// Also sets popupActive class but that will be removed in 2.0.
// Can be set via a data-dojo-attach-point assignment.
// If missing, then focusNode or _buttonNode (if focusNode is missing) will be used.
_popupStateNode: null,
// _aroundNode: [protected] DomNode
// The node to display the popup around.
// Can be set via a data-dojo-attach-point assignment.
// If missing, then domNode will be used.
_aroundNode: null,
// dropDown: [protected] Widget
// The widget to display as a popup. This widget *must* be
// defined before the startup function is called.
dropDown: null,
// autoWidth: [protected] Boolean
// Set to true to make the drop down at least as wide as this
// widget. Set to false if the drop down should just be its
// default width.
autoWidth: true,
// forceWidth: [protected] Boolean
// Set to true to make the drop down exactly as wide as this
// widget. Overrides autoWidth.
forceWidth: false,
// maxHeight: [protected] Integer
// The max height for our dropdown.
// Any dropdown taller than this will have scrollbars.
// Set to 0 for no max height, or -1 to limit height to available space in viewport
maxHeight: -1,
// dropDownPosition: [const] String[]
// This variable controls the position of the drop down.
// It's an array of strings with the following values:
//
// - before: places drop down to the left of the target node/widget, or to the right in
// the case of RTL scripts like Hebrew and Arabic
// - after: places drop down to the right of the target node/widget, or to the left in
// the case of RTL scripts like Hebrew and Arabic
// - above: drop down goes above target node
// - below: drop down goes below target node
//
// The list is positions is tried, in order, until a position is found where the drop down fits
// within the viewport.
//
dropDownPosition: ["below", "above"],
// _stopClickEvents: Boolean
// When set to false, the click events will not be stopped, in
// case you want to use them in your subclass
_stopClickEvents: true,
_onDropDownMouseDown: function(/*Event*/ e){
// summary:
// Callback when the user mousedown/touchstart on the arrow icon.
if(this.disabled || this.readOnly){
return;
}
// Prevent default to stop things like text selection, but don't stop propagation, so that:
// 1. TimeTextBox etc. can focus the on mousedown
// 2. dropDownButtonActive class applied by _CssStateMixin (on button depress)
// 3. user defined onMouseDown handler fires
e.preventDefault();
this._docHandler = this.own(on(this.ownerDocument, touch.release, lang.hitch(this, "_onDropDownMouseUp")))[0];
this.toggleDropDown();
},
_onDropDownMouseUp: function(/*Event?*/ e){
// summary:
// Callback on mouseup/touchend after mousedown/touchstart on the arrow icon.
// Note that this function is called regardless of what node the event occurred on (but only after
// a mousedown/touchstart on the arrow).
//
// If the drop down is a simple menu and the cursor is over the menu, we execute it, otherwise, we focus our
// drop down widget. If the event is missing, then we are not
// a mouseup event.
//
// This is useful for the common mouse movement pattern
// with native browser `