summaryrefslogtreecommitdiff
path: root/lib/dijit/form/_AutoCompleterMixin.js.uncompressed.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dijit/form/_AutoCompleterMixin.js.uncompressed.js')
-rw-r--r--lib/dijit/form/_AutoCompleterMixin.js.uncompressed.js581
1 files changed, 0 insertions, 581 deletions
diff --git a/lib/dijit/form/_AutoCompleterMixin.js.uncompressed.js b/lib/dijit/form/_AutoCompleterMixin.js.uncompressed.js
deleted file mode 100644
index edbc137a2..000000000
--- a/lib/dijit/form/_AutoCompleterMixin.js.uncompressed.js
+++ /dev/null
@@ -1,581 +0,0 @@
-define("dijit/form/_AutoCompleterMixin", [
- "dojo/data/util/filter", // patternToRegExp
- "dojo/_base/declare", // declare
- "dojo/dom-attr", // domAttr.get
- "dojo/_base/event", // event.stop
- "dojo/keys",
- "dojo/_base/lang", // lang.clone lang.hitch
- "dojo/query", // query
- "dojo/regexp", // regexp.escapeString
- "dojo/sniff", // has("ie")
- "dojo/string", // string.substitute
- "./DataList",
- "../registry", // registry.byId
- "./_TextBoxMixin", // defines _TextBoxMixin.selectInputText
- "./_SearchMixin"
-], function(filter, declare, domAttr, event, keys, lang, query, regexp, has, string,
- DataList, registry, _TextBoxMixin, SearchMixin){
-
- // module:
- // dijit/form/_AutoCompleterMixin
-
- return declare("dijit.form._AutoCompleterMixin", SearchMixin, {
- // summary:
- // A mixin that implements the base functionality for `dijit/form/ComboBox`/`dijit/form/FilteringSelect`
- // description:
- // All widgets that mix in dijit/form/_AutoCompleterMixin must extend `dijit/form/_FormValueWidget`.
- // tags:
- // protected
-
- // item: Object
- // This is the item returned by the dojo/store/api/Store implementation that
- // provides the data for this ComboBox, it's the currently selected item.
- item: null,
-
- // autoComplete: Boolean
- // If user types 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,
-
- // highlightMatch: String
- // One of: "first", "all" or "none".
- //
- // If the ComboBox/FilteringSelect opens with the search results and the searched
- // string can be found, it will be highlighted. If set to "all"
- // then will probably want to change `queryExpr` parameter to '*${0}*'
- //
- // Highlighting is only performed when `labelType` is "text", so as to not
- // interfere with any HTML markup an HTML label might contain.
- highlightMatch: "first",
-
- // labelAttr: String?
- // The entries in the drop down list come from this attribute in the
- // dojo.data items.
- // If not specified, the searchAttr attribute is used instead.
- labelAttr: "",
-
- // labelType: String
- // Specifies how to interpret the labelAttr in the data store items.
- // Can be "html" or "text".
- labelType: "text",
-
- // Flags to _HasDropDown to limit height of drop down to make it fit in viewport
- maxHeight: -1,
-
- // For backwards compatibility let onClick events propagate, even clicks on the down arrow button
- _stopClickEvents: false,
-
- _getCaretPos: function(/*DomNode*/ element){
- // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
- var pos = 0;
- if(typeof(element.selectionStart) == "number"){
- // FIXME: this is totally borked on Moz < 1.3. Any recourse?
- pos = element.selectionStart;
- }else if(has("ie")){
- // in the case of a mouse click in a popup being handled,
- // then the win.doc.selection is not the textarea, but the popup
- // var r = win.doc.selection.createRange();
- // hack to get IE 6 to play nice. What a POS browser.
- var tr = element.ownerDocument.selection.createRange().duplicate();
- var ntr = element.createTextRange();
- tr.move("character",0);
- ntr.move("character",0);
- try{
- // If control doesn't 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);
- pos = String(ntr.text).replace(/\r/g,"").length;
- }catch(e){
- // If focus has shifted, 0 is fine for caret pos.
- }
- }
- return pos;
- },
-
- _setCaretPos: function(/*DomNode*/ element, /*Number*/ location){
- location = parseInt(location);
- _TextBoxMixin.selectInputText(element, location, location);
- },
-
- _setDisabledAttr: function(/*Boolean*/ value){
- // Additional code to set disabled state of ComboBox node.
- // Overrides _FormValueWidget._setDisabledAttr() or ValidationTextBox._setDisabledAttr().
- this.inherited(arguments);
- this.domNode.setAttribute("aria-disabled", value ? "true" : "false");
- },
-
- _onKey: function(/*Event*/ evt){
- // summary:
- // Handles keyboard events
-
- if(evt.charCode >= 32){ return; } // alphanumeric reserved for searching
-
- var key = evt.charCode || evt.keyCode;
-
- // except for cutting/pasting case - ctrl + x/v
- if(key == keys.ALT || key == keys.CTRL || key == keys.META || key == keys.SHIFT){
- return; // throw out spurious events
- }
-
- var pw = this.dropDown;
- var highlighted = null;
- this._abortQuery();
-
- // _HasDropDown will do some of the work:
- //
- // 1. when drop down is not yet shown:
- // - if user presses the down arrow key, call loadDropDown()
- // 2. when drop down is already displayed:
- // - on ESC key, call closeDropDown()
- // - otherwise, call dropDown.handleKey() to process the keystroke
- this.inherited(arguments);
-
- if(evt.altKey || evt.ctrlKey || evt.metaKey){ return; } // don't process keys with modifiers - but we want shift+TAB
-
- if(this._opened){
- highlighted = pw.getHighlightedOption();
- }
- switch(key){
- case keys.PAGE_DOWN:
- case keys.DOWN_ARROW:
- case keys.PAGE_UP:
- case keys.UP_ARROW:
- // Keystroke caused ComboBox_menu to move to a different item.
- // Copy new item to <input> box.
- if(this._opened){
- this._announceOption(highlighted);
- }
- event.stop(evt);
- break;
-
- case keys.ENTER:
- // prevent submitting form if user presses enter. Also
- // prevent accepting the value if either Next or Previous
- // are selected
- if(highlighted){
- // only stop event on prev/next
- if(highlighted == pw.nextButton){
- this._nextSearch(1);
- event.stop(evt); // prevent submit
- break;
- }else if(highlighted == pw.previousButton){
- this._nextSearch(-1);
- event.stop(evt); // prevent submit
- break;
- }
- event.stop(evt); // prevent submit if ENTER was to choose an item
- }else{
- // Update 'value' (ex: KY) according to currently displayed text
- this._setBlurValue(); // set value if needed
- this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting
- }
- // fall through
-
- case keys.TAB:
- var newvalue = this.get('displayedValue');
- // if the user had More Choices selected fall into the
- // _onBlur handler
- if(pw && (
- newvalue == pw._messages["previousMessage"] ||
- newvalue == pw._messages["nextMessage"])
- ){
- break;
- }
- if(highlighted){
- this._selectOption(highlighted);
- }
- // fall through
-
- case keys.ESCAPE:
- if(this._opened){
- this._lastQuery = null; // in case results come back later
- this.closeDropDown();
- }
- break;
- }
- },
-
- _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.
-
- var fn = this.focusNode;
-
- // IE7: clear selection so next highlight works all the time
- _TextBoxMixin.selectInputText(fn, fn.value.length);
- // does text autoComplete the value in the textbox?
- var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr';
- if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){
- var cpos = this.autoComplete ? this._getCaretPos(fn) : fn.value.length;
- // only try to extend if we added the last character at the end of the input
- if((cpos+1) > fn.value.length){
- // only add to input node as we would overwrite Capitalisation of chars
- // actually, that is ok
- fn.value = text;//.substr(cpos);
- // visually highlight the autocompleted characters
- _TextBoxMixin.selectInputText(fn, cpos);
- }
- }else{
- // text does not autoComplete; replace the whole value and highlight
- fn.value = text;
- _TextBoxMixin.selectInputText(fn);
- }
- },
-
- _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){
- // summary:
- // Callback when a search completes.
- // description:
- // 1. generates drop-down list and calls _showResultList() to display it
- // 2. if this result list is from user pressing "more choices"/"previous choices"
- // then tell screen reader to announce new option
- var wasSelected = this.dropDown.getHighlightedOption();
- this.dropDown.clearResultList();
- if(!results.length && options.start == 0){ // if no results and not just the previous choices button
- this.closeDropDown();
- return;
- }
- this._nextSearch = this.dropDown.onPage = lang.hitch(this, function(direction){
- results.nextPage(direction !== -1);
- this.focus();
- });
-
- // 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.
-
- this.dropDown.createOptions(
- results,
- options,
- lang.hitch(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("direction" in options){
- if(options.direction){
- this.dropDown.highlightFirstOption();
- }else if(!options.direction){
- this.dropDown.highlightLastOption();
- }
- if(wasSelected){
- this._announceOption(this.dropDown.getHighlightedOption());
- }
- }else if(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.
- && !/^[*]+$/.test(query[this.searchAttr].toString())){
- this._announceOption(this.dropDown.containerNode.firstChild.nextSibling); // 1st real item
- }
- },
-
- _showResultList: function(){
- // summary:
- // Display the drop down if not already displayed, or if it is displayed, then
- // reposition it if necessary (reposition may be necessary if drop down's height changed).
- this.closeDropDown(true);
- this.openDropDown();
- this.domNode.setAttribute("aria-expanded", "true");
- },
-
- loadDropDown: function(/*Function*/ /*===== callback =====*/){
- // Overrides _HasDropDown.loadDropDown().
- // This is called when user has pressed button icon or pressed the down arrow key
- // to open the drop down.
- this._startSearchAll();
- },
-
- isLoaded: function(){
- // signal to _HasDropDown that it needs to call loadDropDown() to load the
- // drop down asynchronously before displaying it
- return false;
- },
-
- closeDropDown: function(){
- // Overrides _HasDropDown.closeDropDown(). Closes the drop down (assuming that it's open).
- // This method is the callback when the user types ESC or clicking
- // the button icon while the drop down is open. It's also called by other code.
- this._abortQuery();
- if(this._opened){
- this.inherited(arguments);
- this.domNode.setAttribute("aria-expanded", "false");
- this.focusNode.removeAttribute("aria-activedescendant");
- }
- },
-
- _setBlurValue: function(){
- // 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.get('displayedValue');
- var pw = this.dropDown;
- if(pw && (
- newvalue == pw._messages["previousMessage"] ||
- newvalue == pw._messages["nextMessage"]
- )
- ){
- this._setValueAttr(this._lastValueReported, true);
- }else if(typeof this.item == "undefined"){
- // Update 'value' (ex: KY) according to currently displayed text
- this.item = null;
- this.set('displayedValue', newvalue);
- }else{
- if(this.value != this._lastValueReported){
- this._handleOnChange(this.value, true);
- }
- this._refreshState();
- }
- },
-
- _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
- // summary:
- // Set the displayed valued in the input box, and the hidden value
- // that gets submitted, based on a dojo.data store item.
- // description:
- // Users shouldn't call this function; they should be calling
- // set('item', value)
- // tags:
- // private
- var value = '';
- if(item){
- if(!displayedValue){
- displayedValue = this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API)
- this.store.getValue(item, this.searchAttr) : item[this.searchAttr];
- }
- value = this._getValueField() != this.searchAttr ? this.store.getIdentity(item) : displayedValue;
- }
- this.set('value', value, priorityChange, displayedValue, item);
- },
-
- _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){
- return;
- }
- // pull the text value from the item attached to the DOM node
- var newValue;
- if(node == this.dropDown.nextButton ||
- node == this.dropDown.previousButton){
- newValue = node.innerHTML;
- this.item = undefined;
- this.value = '';
- }else{
- var item = this.dropDown.items[node.getAttribute("item")];
- newValue = (this.store._oldAPI ? // remove getValue() for 2.0 (old dojo.data API)
- this.store.getValue(item, this.searchAttr) : item[this.searchAttr]).toString();
- this.set('item', item, false, newValue);
- }
- // get the text that the user manually entered (cut off autocompleted text)
- this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length);
- // set up ARIA activedescendant
- this.focusNode.setAttribute("aria-activedescendant", domAttr.get(node, "id"));
- // autocomplete the rest of the option to announce change
- this._autoCompleteText(newValue);
- },
-
- _selectOption: function(/*DomNode*/ target){
- // summary:
- // Menu callback function, called when an item in the menu is selected.
- this.closeDropDown();
- if(target){
- this._announceOption(target);
- }
- this._setCaretPos(this.focusNode, this.focusNode.value.length);
- this._handleOnChange(this.value, true);
- },
-
- _startSearchAll: function(){
- this._startSearch('');
- },
-
- _startSearchFromInput: function(){
- this.item = undefined; // undefined means item needs to be set
- this.inherited(arguments);
- },
-
- _startSearch: function(/*String*/ key){
- // summary:
- // Starts a search for elements matching key (key=="" means to return all items),
- // and calls _openResultList() when the search completes, to display the results.
- if(!this.dropDown){
- var popupId = this.id + "_popup",
- dropDownConstructor = lang.isString(this.dropDownClass) ?
- lang.getObject(this.dropDownClass, false) : this.dropDownClass;
- this.dropDown = new dropDownConstructor({
- onChange: lang.hitch(this, this._selectOption),
- id: popupId,
- dir: this.dir,
- textDir: this.textDir
- });
- this.focusNode.removeAttribute("aria-activedescendant");
- this.textbox.setAttribute("aria-owns",popupId); // associate popup with textbox
- }
- this._lastInput = key; // Store exactly what was entered by the user.
- this.inherited(arguments);
- },
-
- _getValueField: function(){
- // summary:
- // Helper for postMixInProperties() to set this.value based on data inlined into the markup.
- // Returns the attribute name in the item (in dijit/form/_ComboBoxDataStore) to use as the value.
- return this.searchAttr;
- },
-
- //////////// INITIALIZATION METHODS ///////////////////////////////////////
-
- postMixInProperties: function(){
- this.inherited(arguments);
- if(!this.store){
- var srcNodeRef = this.srcNodeRef;
- // if user didn't specify store, then assume there are option tags
- this.store = new DataList({}, srcNodeRef);
-
- // 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
- // Firefox and Safari set value
- // IE6 and Opera set selectedIndex, which is automatically set
- // by the selected attribute of an option tag
- // IE6 does not set value, Opera sets value = selectedIndex
- if(!("value" in this.params)){
- var item = (this.item = this.store.fetchSelectedItem());
- if(item){
- var valueField = this._getValueField();
- // remove getValue() for 2.0 (old dojo.data API)
- this.value = this.store._oldAPI ? this.store.getValue(item, valueField) : item[valueField];
- }
- }
- }
- },
-
- postCreate: function(){
- // summary:
- // Subclasses must call this method from their postCreate() methods
- // tags:
- // protected
-
- // find any associated label element and add to ComboBox node.
- var label=query('label[for="'+this.id+'"]');
- if(label.length){
- if(!label[0].id){ label[0].id = this.id + "_label"; }
- this.domNode.setAttribute("aria-labelledby", label[0].id);
-
- }
- this.inherited(arguments);
- this.connect(this, "onSearch", "_openResultList");
- },
-
- _getMenuLabelFromItem: function(/*Item*/ item){
- var label = this.labelFunc(item, this.store),
- labelType = this.labelType;
- // If labelType is not "text" we don't want to screw any markup ot whatever.
- if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){
- label = this.doHighlight(label, this._lastInput);
- labelType = "html";
- }
- return {html: labelType == "html", label: label};
- },
-
- doHighlight: function(/*String*/ label, /*String*/ find){
- // summary:
- // Highlights the string entered by the user in the menu. By default this
- // highlights the first occurrence found. Override this method
- // to implement your custom highlighting.
- // tags:
- // protected
-
- var
- // Add (g)lobal modifier when this.highlightMatch == "all" and (i)gnorecase when this.ignoreCase == true
- modifiers = (this.ignoreCase ? "i" : "") + (this.highlightMatch == "all" ? "g" : ""),
- i = this.queryExpr.indexOf("${0}");
- find = regexp.escapeString(find); // escape regexp special chars
- //If < appears in label, and user presses t, we don't want to highlight the t in the escaped "&lt;"
- //first find out every occurences of "find", wrap each occurence in a pair of "\uFFFF" characters (which
- //should not appear in any string). then html escape the whole string, and replace '\uFFFF" with the
- //HTML highlight markup.
- return this._escapeHtml(label.replace(
- new RegExp((i == 0 ? "^" : "") + "("+ find +")" + (i == (this.queryExpr.length - 4) ? "$" : ""), modifiers),
- '\uFFFF$1\uFFFF')).replace(
- /\uFFFF([^\uFFFF]+)\uFFFF/g, '<span class="dijitComboBoxHighlightMatch">$1</span>'
- ); // returns String, (almost) valid HTML (entities encoded)
- },
-
- _escapeHtml: function(/*String*/ str){
- // TODO Should become dojo.html.entities(), when exists use instead
- // summary:
- // Adds escape sequences for special characters in XML: `&<>"'`
- str = String(str).replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
- .replace(/>/gm, "&gt;").replace(/"/gm, "&quot;"); //balance"
- return str; // string
- },
-
- reset: function(){
- // Overrides the _FormWidget.reset().
- // Additionally reset the .item (to clean up).
- this.item = null;
- this.inherited(arguments);
- },
-
- labelFunc: function(item, store){
- // summary:
- // Computes the label to display based on the dojo.data store item.
- // item: Object
- // The item from the store
- // store: dojo/store/api/Store
- // The store.
- // returns:
- // The label that the ComboBox should display
- // tags:
- // private
-
- // Use toString() because XMLStore returns an XMLItem whereas this
- // method is expected to return a String (#9354).
- // Remove getValue() for 2.0 (old dojo.data API)
- return (store._oldAPI ? store.getValue(item, this.labelAttr || this.searchAttr) :
- item[this.labelAttr || this.searchAttr]).toString(); // String
- },
-
- _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){
- // summary:
- // Hook so set('value', value) works.
- // description:
- // Sets the value of the select.
- this._set("item", item||null); // value not looked up in store
- if(value == null /* or undefined */){ value = ''; } // null translates to blank
- this.inherited(arguments);
- },
- _setTextDirAttr: function(/*String*/ textDir){
- // summary:
- // Setter for textDir, needed for the dropDown's textDir update.
- // description:
- // Users shouldn't call this function; they should be calling
- // set('textDir', value)
- // tags:
- // private
- this.inherited(arguments);
- // update the drop down also (_ComboBoxMenuMixin)
- if(this.dropDown){
- this.dropDown._set("textDir", textDir);
- }
- }
- });
-});