summaryrefslogtreecommitdiff
path: root/lib/dijit/form/_FormSelectWidget.js.uncompressed.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dijit/form/_FormSelectWidget.js.uncompressed.js')
-rw-r--r--lib/dijit/form/_FormSelectWidget.js.uncompressed.js707
1 files changed, 0 insertions, 707 deletions
diff --git a/lib/dijit/form/_FormSelectWidget.js.uncompressed.js b/lib/dijit/form/_FormSelectWidget.js.uncompressed.js
deleted file mode 100644
index 4a40c51d0..000000000
--- a/lib/dijit/form/_FormSelectWidget.js.uncompressed.js
+++ /dev/null
@@ -1,707 +0,0 @@
-define("dijit/form/_FormSelectWidget", [
- "dojo/_base/array", // array.filter array.forEach array.map array.some
- "dojo/_base/Deferred",
- "dojo/aspect", // aspect.after
- "dojo/data/util/sorter", // util.sorter.createSortFunction
- "dojo/_base/declare", // declare
- "dojo/dom", // dom.setSelectable
- "dojo/dom-class", // domClass.toggle
- "dojo/_base/kernel", // _scopeName
- "dojo/_base/lang", // lang.delegate lang.isArray lang.isObject lang.hitch
- "dojo/query", // query
- "dojo/when",
- "dojo/store/util/QueryResults",
- "./_FormValueWidget"
-], function(array, Deferred, aspect, sorter, declare, dom, domClass, kernel, lang, query, when,
- QueryResults, _FormValueWidget){
-
-// module:
-// dijit/form/_FormSelectWidget
-
-/*=====
-var __SelectOption = {
- // value: String
- // The value of the option. Setting to empty (or missing) will
- // place a separator at that location
- // label: String
- // The label for our option. It can contain html tags.
- // selected: Boolean
- // Whether or not we are a selected option
- // disabled: Boolean
- // Whether or not this specific option is disabled
-};
-=====*/
-
-var _FormSelectWidget = declare("dijit.form._FormSelectWidget", _FormValueWidget, {
- // summary:
- // Extends _FormValueWidget in order to provide "select-specific"
- // values - i.e., those values that are unique to `<select>` elements.
- // This also provides the mechanism for reading the elements from
- // a store, if desired.
-
- // multiple: [const] Boolean
- // Whether or not we are multi-valued
- multiple: false,
-
- // options: __SelectOption[]
- // The set of options for our select item. Roughly corresponds to
- // the html `<option>` tag.
- options: null,
-
- // store: dojo/store/api/Store
- // A store to use for getting our list of options - rather than reading them
- // from the `<option>` html tags. Should support getIdentity().
- // For back-compat store can also be a dojo/data/api/Identity.
- store: null,
-
- // query: object
- // A query to use when fetching items from our store
- query: null,
-
- // queryOptions: object
- // Query options to use when fetching from the store
- queryOptions: null,
-
- // labelAttr: String?
- // The entries in the drop down list come from this attribute in the dojo.store items.
- // If ``store`` is set, labelAttr must be set too, unless store is an old-style
- // dojo.data store rather than a new dojo/store.
- labelAttr: "",
-
- // onFetch: Function
- // A callback to do with an onFetch - but before any items are actually
- // iterated over (i.e. to filter even further what you want to add)
- onFetch: null,
-
- // sortByLabel: Boolean
- // Flag to sort the options returned from a store by the label of
- // the store.
- sortByLabel: true,
-
-
- // loadChildrenOnOpen: Boolean
- // By default loadChildren is called when the items are fetched from the
- // store. This property allows delaying loadChildren (and the creation
- // of the options/menuitems) until the user clicks the button to open the
- // dropdown.
- loadChildrenOnOpen: false,
-
- // onLoadDeferred: [readonly] dojo.Deferred
- // This is the `dojo.Deferred` returned by setStore().
- // Calling onLoadDeferred.then() registers your
- // callback to be called only once, when the prior setStore completes.
- onLoadDeferred: null,
-
- getOptions: function(/*anything*/ valueOrIdx){
- // summary:
- // Returns a given option (or options).
- // valueOrIdx:
- // If passed in as a string, that string is used to look up the option
- // in the array of options - based on the value property.
- // (See dijit/form/_FormSelectWidget.__SelectOption).
- //
- // If passed in a number, then the option with the given index (0-based)
- // within this select will be returned.
- //
- // If passed in a dijit/form/_FormSelectWidget.__SelectOption, the same option will be
- // returned if and only if it exists within this select.
- //
- // If passed an array, then an array will be returned with each element
- // in the array being looked up.
- //
- // If not passed a value, then all options will be returned
- //
- // returns:
- // The option corresponding with the given value or index. null
- // is returned if any of the following are true:
- //
- // - A string value is passed in which doesn't exist
- // - An index is passed in which is outside the bounds of the array of options
- // - A dijit/form/_FormSelectWidget.__SelectOption is passed in which is not a part of the select
-
- // NOTE: the compare for passing in a dijit/form/_FormSelectWidget.__SelectOption checks
- // if the value property matches - NOT if the exact option exists
- // NOTE: if passing in an array, null elements will be placed in the returned
- // array when a value is not found.
- var lookupValue = valueOrIdx, opts = this.options || [], l = opts.length;
-
- if(lookupValue === undefined){
- return opts; // __SelectOption[]
- }
- if(lang.isArray(lookupValue)){
- return array.map(lookupValue, "return this.getOptions(item);", this); // __SelectOption[]
- }
- if(lang.isObject(valueOrIdx)){
- // We were passed an option - so see if it's in our array (directly),
- // and if it's not, try and find it by value.
- if(!array.some(this.options, function(o, idx){
- if(o === lookupValue ||
- (o.value && o.value === lookupValue.value)){
- lookupValue = idx;
- return true;
- }
- return false;
- })){
- lookupValue = -1;
- }
- }
- if(typeof lookupValue == "string"){
- for(var i=0; i<l; i++){
- if(opts[i].value === lookupValue){
- lookupValue = i;
- break;
- }
- }
- }
- if(typeof lookupValue == "number" && lookupValue >= 0 && lookupValue < l){
- return this.options[lookupValue]; // __SelectOption
- }
- return null; // null
- },
-
- addOption: function(/*__SelectOption|__SelectOption[]*/ option){
- // summary:
- // Adds an option or options to the end of the select. If value
- // of the option is empty or missing, a separator is created instead.
- // Passing in an array of options will yield slightly better performance
- // since the children are only loaded once.
- if(!lang.isArray(option)){ option = [option]; }
- array.forEach(option, function(i){
- if(i && lang.isObject(i)){
- this.options.push(i);
- }
- }, this);
- this._loadChildren();
- },
-
- removeOption: function(/*String|__SelectOption|Number|Array*/ valueOrIdx){
- // summary:
- // Removes the given option or options. You can remove by string
- // (in which case the value is removed), number (in which case the
- // index in the options array is removed), or select option (in
- // which case, the select option with a matching value is removed).
- // You can also pass in an array of those values for a slightly
- // better performance since the children are only loaded once.
- if(!lang.isArray(valueOrIdx)){ valueOrIdx = [valueOrIdx]; }
- var oldOpts = this.getOptions(valueOrIdx);
- array.forEach(oldOpts, function(i){
- // We can get null back in our array - if our option was not found. In
- // that case, we don't want to blow up...
- if(i){
- this.options = array.filter(this.options, function(node){
- return (node.value !== i.value || node.label !== i.label);
- });
- this._removeOptionItem(i);
- }
- }, this);
- this._loadChildren();
- },
-
- updateOption: function(/*__SelectOption|__SelectOption[]*/ newOption){
- // summary:
- // Updates the values of the given option. The option to update
- // is matched based on the value of the entered option. Passing
- // in an array of new options will yield better performance since
- // the children will only be loaded once.
- if(!lang.isArray(newOption)){ newOption = [newOption]; }
- array.forEach(newOption, function(i){
- var oldOpt = this.getOptions(i), k;
- if(oldOpt){
- for(k in i){ oldOpt[k] = i[k]; }
- }
- }, this);
- this._loadChildren();
- },
-
- setStore: function(store,
- selectedValue,
- fetchArgs){
- // summary:
- // Sets the store you would like to use with this select widget.
- // The selected value is the value of the new store to set. This
- // function returns the original store, in case you want to reuse
- // it or something.
- // store: dojo/store/api/Store
- // The dojo.store you would like to use - it MUST implement getIdentity()
- // and MAY implement observe().
- // For backwards-compatibility this can also be a data.data store, in which case
- // it MUST implement dojo/data/api/Identity,
- // and MAY implement dojo/data/api/Notification.
- // selectedValue: anything?
- // The value that this widget should set itself to *after* the store
- // has been loaded
- // fetchArgs: Object?
- // Hash of parameters to set filter on store, etc.
- //
- // - query: new value for Select.query,
- // - queryOptions: new value for Select.queryOptions,
- // - onFetch: callback function for each item in data (Deprecated)
- var oStore = this.store;
- fetchArgs = fetchArgs || {};
-
- if(oStore !== store){
- // Our store has changed, so cancel any listeners on old store (remove for 2.0)
- var h;
- while((h = this._notifyConnections.pop())){ h.remove(); }
-
- // For backwards-compatibility, accept dojo.data store in addition to dojo.store.store. Remove in 2.0.
- if(!store.get){
- lang.mixin(store, {
- _oldAPI: true,
- get: function(id){
- // summary:
- // Retrieves an object by it's identity. This will trigger a fetchItemByIdentity.
- // Like dojo.store.DataStore.get() except returns native item.
- var deferred = new Deferred();
- this.fetchItemByIdentity({
- identity: id,
- onItem: function(object){
- deferred.resolve(object);
- },
- onError: function(error){
- deferred.reject(error);
- }
- });
- return deferred.promise;
- },
- query: function(query, options){
- // summary:
- // Queries the store for objects. Like dojo/store/DataStore.query()
- // except returned Deferred contains array of native items.
- var deferred = new Deferred(function(){ if(fetchHandle.abort){ fetchHandle.abort(); } } );
- deferred.total = new Deferred();
- var fetchHandle = this.fetch(lang.mixin({
- query: query,
- onBegin: function(count){
- deferred.total.resolve(count);
- },
- onComplete: function(results){
- deferred.resolve(results);
- },
- onError: function(error){
- deferred.reject(error);
- }
- }, options));
- return new QueryResults(deferred);
- }
- });
-
- if(store.getFeatures()["dojo.data.api.Notification"]){
- this._notifyConnections = [
- aspect.after(store, "onNew", lang.hitch(this, "_onNewItem"), true),
- aspect.after(store, "onDelete", lang.hitch(this, "_onDeleteItem"), true),
- aspect.after(store, "onSet", lang.hitch(this, "_onSetItem"), true)
- ];
- }
- }
- this._set("store", store); // Our store has changed, so update our notifications
- }
-
- // Remove existing options (if there are any)
- if(this.options && this.options.length){
- this.removeOption(this.options);
- }
-
- // Cancel listener for updates to old store
- if(this._queryRes && this._queryRes.close){
- this._queryRes.close();
- }
-
- // If user has specified new query and query options along with this new store, then use them.
- if(fetchArgs.query){
- this._set("query", fetchArgs.query);
- this._set("queryOptions", fetchArgs.queryOptions);
- }
-
- // Add our new options
- if(store){
- this._loadingStore = true;
- this.onLoadDeferred = new Deferred();
-
- // Run query
- // Save result in this._queryRes so we can cancel the listeners we register below
- this._queryRes = store.query(this.query, this.queryOptions);
- when(this._queryRes, lang.hitch(this, function(items){
-
- if(this.sortByLabel && !fetchArgs.sort && items.length){
- if(items[0].getValue){
- // Old dojo.data API to access items, remove for 2.0
- items.sort(sorter.createSortFunction([{
- attribute: store.getLabelAttributes(items[0])[0]
- }], store));
- }else{
- var labelAttr = this.labelAttr;
- items.sort(function(a, b){
- return a[labelAttr] > b[labelAttr] ? 1 : b[labelAttr] > a[labelAttr] ? -1 : 0;
- });
- }
- }
-
- if(fetchArgs.onFetch){
- items = fetchArgs.onFetch.call(this, items, fetchArgs);
- }
-
- // TODO: Add these guys as a batch, instead of separately
- array.forEach(items, function(i){
- this._addOptionForItem(i);
- }, this);
-
- // Register listener for store updates
- if(this._queryRes.observe){
- this._queryRes.observe(lang.hitch(this, function(object, deletedFrom, insertedInto){
- if(deletedFrom == insertedInto){
- this._onSetItem(object);
- }else{
- if(deletedFrom != -1){
- this._onDeleteItem(object);
- }
- if(insertedInto != -1){
- this._onNewItem(object);
- }
- }
- }), true);
- }
-
- // Set our value (which might be undefined), and then tweak
- // it to send a change event with the real value
- this._loadingStore = false;
- this.set("value", "_pendingValue" in this ? this._pendingValue : selectedValue);
- delete this._pendingValue;
-
- if(!this.loadChildrenOnOpen){
- this._loadChildren();
- }else{
- this._pseudoLoadChildren(items);
- }
- this.onLoadDeferred.resolve(true);
- this.onSetStore();
- }), function(err){
- console.error('dijit.form.Select: ' + err.toString());
- this.onLoadDeferred.reject(err);
- });
- }
- return oStore; // dojo/data/api/Identity
- },
-
- // TODO: implement set() and watch() for store and query, although not sure how to handle
- // setting them individually rather than together (as in setStore() above)
-
- _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
- // summary:
- // set the value of the widget.
- // If a string is passed, then we set our value from looking it up.
- if(!this._onChangeActive){ priorityChange = null; }
- if(this._loadingStore){
- // Our store is loading - so save our value, and we'll set it when
- // we're done
- this._pendingValue = newValue;
- return;
- }
- var opts = this.getOptions() || [];
- if(!lang.isArray(newValue)){
- newValue = [newValue];
- }
- array.forEach(newValue, function(i, idx){
- if(!lang.isObject(i)){
- i = i + "";
- }
- if(typeof i === "string"){
- newValue[idx] = array.filter(opts, function(node){
- return node.value === i;
- })[0] || {value: "", label: ""};
- }
- }, this);
-
- // Make sure some sane default is set
- newValue = array.filter(newValue, function(i){ return i && i.value; });
- if(!this.multiple && (!newValue[0] || !newValue[0].value) && opts.length){
- newValue[0] = opts[0];
- }
- array.forEach(opts, function(i){
- i.selected = array.some(newValue, function(v){ return v.value === i.value; });
- });
- var val = array.map(newValue, function(i){ return i.value; }),
- disp = array.map(newValue, function(i){ return i.label; });
-
- if(typeof val == "undefined" || typeof val[0] == "undefined"){ return; } // not fully initialized yet or a failed value lookup
- this._setDisplay(this.multiple ? disp : disp[0]);
- this.inherited(arguments, [ this.multiple ? val : val[0], priorityChange ]);
- this._updateSelection();
- },
-
- _getDisplayedValueAttr: function(){
- // summary:
- // returns the displayed value of the widget
- var val = this.get("value");
- if(!lang.isArray(val)){
- val = [val];
- }
- var ret = array.map(this.getOptions(val), function(v){
- if(v && "label" in v){
- return v.label;
- }else if(v){
- return v.value;
- }
- return null;
- }, this);
- return this.multiple ? ret : ret[0];
- },
-
- _loadChildren: function(){
- // summary:
- // Loads the children represented by this widget's options.
- // reset the menu to make it populatable on the next click
- if(this._loadingStore){ return; }
- array.forEach(this._getChildren(), function(child){
- child.destroyRecursive();
- });
- // Add each menu item
- array.forEach(this.options, this._addOptionItem, this);
-
- // Update states
- this._updateSelection();
- },
-
- _updateSelection: function(){
- // summary:
- // Sets the "selected" class on the item for styling purposes
- this._set("value", this._getValueFromOpts());
- var val = this.value;
- if(!lang.isArray(val)){
- val = [val];
- }
- if(val && val[0]){
- array.forEach(this._getChildren(), function(child){
- var isSelected = array.some(val, function(v){
- return child.option && (v === child.option.value);
- });
- domClass.toggle(child.domNode, this.baseClass.replace(/\s+|$/g, "SelectedOption "), isSelected);
- child.domNode.setAttribute("aria-selected", isSelected ? "true" : "false");
- }, this);
- }
- },
-
- _getValueFromOpts: function(){
- // summary:
- // Returns the value of the widget by reading the options for
- // the selected flag
- var opts = this.getOptions() || [];
- if(!this.multiple && opts.length){
- // Mirror what a select does - choose the first one
- var opt = array.filter(opts, function(i){
- return i.selected;
- })[0];
- if(opt && opt.value){
- return opt.value;
- }else{
- opts[0].selected = true;
- return opts[0].value;
- }
- }else if(this.multiple){
- // Set value to be the sum of all selected
- return array.map(array.filter(opts, function(i){
- return i.selected;
- }), function(i){
- return i.value;
- }) || [];
- }
- return "";
- },
-
- // Internal functions to call when we have store notifications come in
- _onNewItem: function(/*item*/ item, /*Object?*/ parentInfo){
- if(!parentInfo || !parentInfo.parent){
- // Only add it if we are top-level
- this._addOptionForItem(item);
- }
- },
- _onDeleteItem: function(/*item*/ item){
- var store = this.store;
- this.removeOption(store.getIdentity(item));
- },
- _onSetItem: function(/*item*/ item){
- this.updateOption(this._getOptionObjForItem(item));
- },
-
- _getOptionObjForItem: function(item){
- // summary:
- // Returns an option object based off the given item. The "value"
- // of the option item will be the identity of the item, the "label"
- // of the option will be the label of the item.
-
- // remove getLabel() call for 2.0 (it's to support the old dojo.data API)
- var store = this.store,
- label = (this.labelAttr && this.labelAttr in item) ? item[this.labelAttr] : store.getLabel(item),
- value = (label ? store.getIdentity(item) : null);
- return {value: value, label: label, item: item}; // __SelectOption
- },
-
- _addOptionForItem: function(/*item*/ item){
- // summary:
- // Creates (and adds) the option for the given item
- var store = this.store;
- if(store.isItemLoaded && !store.isItemLoaded(item)){
- // We are not loaded - so let's load it and add later.
- // Remove for 2.0 (it's the old dojo.data API)
- store.loadItem({item: item, onItem: function(i){
- this._addOptionForItem(i);
- },
- scope: this});
- return;
- }
- var newOpt = this._getOptionObjForItem(item);
- this.addOption(newOpt);
- },
-
- constructor: function(params /*===== , srcNodeRef =====*/){
- // summary:
- // Create the widget.
- // params: Object|null
- // Hash of initialization parameters for widget, including scalar values (like title, duration etc.)
- // and functions, typically callbacks like onClick.
- // The hash can contain any of the widget's properties, excluding read-only properties.
- // srcNodeRef: DOMNode|String?
- // If a srcNodeRef (DOM node) is specified, replace srcNodeRef with my generated DOM tree
-
- // Saves off our value, if we have an initial one set so we
- // can use it if we have a store as well (see startup())
- this._oValue = (params || {}).value || null;
- this._notifyConnections = []; // remove for 2.0
- },
-
- buildRendering: function(){
- this.inherited(arguments);
- dom.setSelectable(this.focusNode, false);
- },
-
- _fillContent: function(){
- // summary:
- // Loads our options and sets up our dropdown correctly. We
- // don't want any content, so we don't call any inherit chain
- // function.
- if(!this.options){
- this.options =
- this.srcNodeRef
- ? query("> *", this.srcNodeRef).map(
- function(node){
- if(node.getAttribute("type") === "separator"){
- return { value: "", label: "", selected: false, disabled: false };
- }
- return {
- value: (node.getAttribute("data-" + kernel._scopeName + "-value") || node.getAttribute("value")),
- label: String(node.innerHTML),
- // FIXME: disabled and selected are not valid on complex markup children (which is why we're
- // looking for data-dojo-value above. perhaps we should data-dojo-props="" this whole thing?)
- // decide before 1.6
- selected: node.getAttribute("selected") || false,
- disabled: node.getAttribute("disabled") || false
- };
- },
- this)
- : [];
- }
- if(!this.value){
- this._set("value", this._getValueFromOpts());
- }else if(this.multiple && typeof this.value == "string"){
- this._set("value", this.value.split(","));
- }
- },
-
- postCreate: function(){
- // summary:
- // sets up our event handling that we need for functioning
- // as a select
- this.inherited(arguments);
-
- // Make our event connections for updating state
- this.connect(this, "onChange", "_updateSelection");
-
- // moved from startup
- // Connects in our store, if we have one defined
- var store = this.store;
- if(store && (store.getIdentity || store.getFeatures()["dojo.data.api.Identity"])){
- // Temporarily set our store to null so that it will get set
- // and connected appropriately
- this.store = null;
- this.setStore(store, this._oValue);
- }
- },
-
- startup: function(){
- // summary:
- this._loadChildren();
- this.inherited(arguments);
- },
-
- destroy: function(){
- // summary:
- // Clean up our connections
-
- var h;
- while((h = this._notifyConnections.pop())){ h.remove(); }
-
- // Cancel listener for store updates
- if(this._queryRes && this._queryRes.close){
- this._queryRes.close();
- }
-
- this.inherited(arguments);
- },
-
- _addOptionItem: function(/*__SelectOption*/ /*===== option =====*/){
- // summary:
- // User-overridable function which, for the given option, adds an
- // item to the select. If the option doesn't have a value, then a
- // separator is added in that place. Make sure to store the option
- // in the created option widget.
- },
-
- _removeOptionItem: function(/*__SelectOption*/ /*===== option =====*/){
- // summary:
- // User-overridable function which, for the given option, removes
- // its item from the select.
- },
-
- _setDisplay: function(/*String or String[]*/ /*===== newDisplay =====*/){
- // summary:
- // Overridable function which will set the display for the
- // widget. newDisplay is either a string (in the case of
- // single selects) or array of strings (in the case of multi-selects)
- },
-
- _getChildren: function(){
- // summary:
- // Overridable function to return the children that this widget contains.
- return [];
- },
-
- _getSelectedOptionsAttr: function(){
- // summary:
- // hooks into this.attr to provide a mechanism for getting the
- // option items for the current value of the widget.
- return this.getOptions(this.get("value"));
- },
-
- _pseudoLoadChildren: function(/*item[]*/ /*===== items =====*/){
- // summary:
- // a function that will "fake" loading children, if needed, and
- // if we have set to not load children until the widget opens.
- // items:
- // An array of items that will be loaded, when needed
- },
-
- onSetStore: function(){
- // summary:
- // a function that can be connected to in order to receive a
- // notification that the store has finished loading and all options
- // from that store are available
- }
-});
-
-/*=====
-_FormSelectWidget.__SelectOption = __SelectOption;
-=====*/
-
-return _FormSelectWidget;
-
-});