mirror of
https://git.tt-rss.org/git/tt-rss.git
synced 2025-12-18 14:41:30 +00:00
upgrade dojo to 1.8.3 (refs #570)
This commit is contained in:
264
lib/dijit/form/_SearchMixin.js.uncompressed.js
Normal file
264
lib/dijit/form/_SearchMixin.js.uncompressed.js
Normal file
@@ -0,0 +1,264 @@
|
||||
define("dijit/form/_SearchMixin", [
|
||||
"dojo/data/util/filter", // patternToRegExp
|
||||
"dojo/_base/declare", // declare
|
||||
"dojo/_base/event", // event.stop
|
||||
"dojo/keys", // keys
|
||||
"dojo/_base/lang", // lang.clone lang.hitch
|
||||
"dojo/query", // query
|
||||
"dojo/sniff", // has("ie")
|
||||
"dojo/string", // string.substitute
|
||||
"dojo/when",
|
||||
"../registry" // registry.byId
|
||||
], function(filter, declare, event, keys, lang, query, has, string, when, registry){
|
||||
|
||||
// module:
|
||||
// dijit/form/_SearchMixin
|
||||
|
||||
|
||||
return declare("dijit.form._SearchMixin", null, {
|
||||
// summary:
|
||||
// A mixin that implements the base functionality to search a store based upon user-entered text such as
|
||||
// with `dijit/form/ComboBox` or `dijit/form/FilteringSelect`
|
||||
// tags:
|
||||
// protected
|
||||
|
||||
// pageSize: Integer
|
||||
// Argument to data provider.
|
||||
// Specifies maximum number of search results to return per query
|
||||
pageSize: Infinity,
|
||||
|
||||
// store: [const] dojo/store/api/Store
|
||||
// Reference to data provider object used by this ComboBox.
|
||||
// The store must accept an object hash of properties for its query. See `query` and `queryExpr` for details.
|
||||
store: null,
|
||||
|
||||
// fetchProperties: Object
|
||||
// Mixin to the store's fetch.
|
||||
// For example, to set the sort order of the ComboBox menu, pass:
|
||||
// | { sort: [{attribute:"name",descending: true}] }
|
||||
// To override the default queryOptions so that deep=false, do:
|
||||
// | { queryOptions: {ignoreCase: true, deep: false} }
|
||||
fetchProperties:{},
|
||||
|
||||
// query: Object
|
||||
// A query that can be passed to `store` to initially filter the items.
|
||||
// ComboBox overwrites any reference to the `searchAttr` and sets it to the `queryExpr` with the user's input substituted.
|
||||
query: {},
|
||||
|
||||
// searchDelay: Integer
|
||||
// Delay in milliseconds between when user types something and we start
|
||||
// searching based on that value
|
||||
searchDelay: 200,
|
||||
|
||||
// searchAttr: String
|
||||
// Search for items in the data store where this attribute (in the item)
|
||||
// matches what the user typed
|
||||
searchAttr: "name",
|
||||
|
||||
// queryExpr: String
|
||||
// This specifies what query is sent to the data store,
|
||||
// based on what the user has typed. Changing this expression will modify
|
||||
// whether the results are only exact matches, a "starting with" match,
|
||||
// etc.
|
||||
// dojo.data query expression pattern.
|
||||
// `${0}` will be substituted for the user text.
|
||||
// `*` is used for wildcards.
|
||||
// `${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is"
|
||||
queryExpr: "${0}*",
|
||||
|
||||
// ignoreCase: Boolean
|
||||
// Set true if the query should ignore case when matching possible items
|
||||
ignoreCase: true,
|
||||
|
||||
_abortQuery: function(){
|
||||
// stop in-progress query
|
||||
if(this.searchTimer){
|
||||
this.searchTimer = this.searchTimer.remove();
|
||||
}
|
||||
if(this._queryDeferHandle){
|
||||
this._queryDeferHandle = this._queryDeferHandle.remove();
|
||||
}
|
||||
if(this._fetchHandle){
|
||||
if(this._fetchHandle.abort){
|
||||
this._cancelingQuery = true;
|
||||
this._fetchHandle.abort();
|
||||
this._cancelingQuery = false;
|
||||
}
|
||||
if(this._fetchHandle.cancel){
|
||||
this._cancelingQuery = true;
|
||||
this._fetchHandle.cancel();
|
||||
this._cancelingQuery = false;
|
||||
}
|
||||
this._fetchHandle = null;
|
||||
}
|
||||
},
|
||||
|
||||
_processInput: function(/*Event*/ evt){
|
||||
// summary:
|
||||
// Handles input (keyboard/paste) events
|
||||
if(this.disabled || this.readOnly){ return; }
|
||||
var key = evt.charOrCode;
|
||||
|
||||
// except for cutting/pasting case - ctrl + x/v
|
||||
if(evt.altKey || ((evt.ctrlKey || evt.metaKey) && (key != 'x' && key != 'v')) || key == keys.SHIFT){
|
||||
return; // throw out weird key combinations and spurious events
|
||||
}
|
||||
|
||||
var doSearch = false;
|
||||
this._prev_key_backspace = false;
|
||||
|
||||
switch(key){
|
||||
case keys.DELETE:
|
||||
case keys.BACKSPACE:
|
||||
this._prev_key_backspace = true;
|
||||
this._maskValidSubsetError = true;
|
||||
doSearch = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Non char keys (F1-F12 etc..) shouldn't start a search..
|
||||
// Ascii characters and IME input (Chinese, Japanese etc.) should.
|
||||
//IME input produces keycode == 229.
|
||||
doSearch = typeof key == 'string' || key == 229;
|
||||
}
|
||||
if(doSearch){
|
||||
// need to wait a tad before start search so that the event
|
||||
// bubbles through DOM and we have value visible
|
||||
if(!this.store){
|
||||
this.onSearch();
|
||||
}else{
|
||||
this.searchTimer = this.defer("_startSearchFromInput", 1);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
onSearch: function(/*===== results, query, options =====*/){
|
||||
// summary:
|
||||
// Callback when a search completes.
|
||||
//
|
||||
// results: Object
|
||||
// An array of items from the originating _SearchMixin's store.
|
||||
//
|
||||
// query: Object
|
||||
// A copy of the originating _SearchMixin's query property.
|
||||
//
|
||||
// options: Object
|
||||
// The additional parameters sent to the originating _SearchMixin's store, including: start, count, queryOptions.
|
||||
//
|
||||
// tags:
|
||||
// callback
|
||||
},
|
||||
|
||||
_startSearchFromInput: function(){
|
||||
this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g, "\\$1"));
|
||||
},
|
||||
|
||||
_startSearch: function(/*String*/ text){
|
||||
// summary:
|
||||
// Starts a search for elements matching text (text=="" means to return all items),
|
||||
// and calls onSearch(...) when the search completes, to display the results.
|
||||
|
||||
this._abortQuery();
|
||||
var
|
||||
_this = this,
|
||||
// Setup parameters to be passed to store.query().
|
||||
// Create a new query to prevent accidentally querying for a hidden
|
||||
// value from FilteringSelect's keyField
|
||||
query = lang.clone(this.query), // #5970
|
||||
options = {
|
||||
start: 0,
|
||||
count: this.pageSize,
|
||||
queryOptions: { // remove for 2.0
|
||||
ignoreCase: this.ignoreCase,
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
qs = string.substitute(this.queryExpr, [text]),
|
||||
q,
|
||||
startQuery = function(){
|
||||
var resPromise = _this._fetchHandle = _this.store.query(query, options);
|
||||
if(_this.disabled || _this.readOnly || (q !== _this._lastQuery)){
|
||||
return;
|
||||
} // avoid getting unwanted notify
|
||||
when(resPromise, function(res){
|
||||
_this._fetchHandle = null;
|
||||
if(!_this.disabled && !_this.readOnly && (q === _this._lastQuery)){ // avoid getting unwanted notify
|
||||
when(resPromise.total, function(total){
|
||||
res.total = total;
|
||||
var pageSize = _this.pageSize;
|
||||
if(isNaN(pageSize) || pageSize > res.total){ pageSize = res.total; }
|
||||
// Setup method to fetching the next page of results
|
||||
res.nextPage = function(direction){
|
||||
// tell callback the direction of the paging so the screen
|
||||
// reader knows which menu option to shout
|
||||
options.direction = direction = direction !== false;
|
||||
options.count = pageSize;
|
||||
if(direction){
|
||||
options.start += res.length;
|
||||
if(options.start >= res.total){
|
||||
options.count = 0;
|
||||
}
|
||||
}else{
|
||||
options.start -= pageSize;
|
||||
if(options.start < 0){
|
||||
options.count = Math.max(pageSize + options.start, 0);
|
||||
options.start = 0;
|
||||
}
|
||||
}
|
||||
if(options.count <= 0){
|
||||
res.length = 0;
|
||||
_this.onSearch(res, query, options);
|
||||
}else{
|
||||
startQuery();
|
||||
}
|
||||
};
|
||||
_this.onSearch(res, query, options);
|
||||
});
|
||||
}
|
||||
}, function(err){
|
||||
_this._fetchHandle = null;
|
||||
if(!_this._cancelingQuery){ // don't treat canceled query as an error
|
||||
console.error(_this.declaredClass + ' ' + err.toString());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
lang.mixin(options, this.fetchProperties);
|
||||
|
||||
// Generate query
|
||||
if(this.store._oldAPI){
|
||||
// remove this branch for 2.0
|
||||
q = qs;
|
||||
}else{
|
||||
// Query on searchAttr is a regex for benefit of dojo/store/Memory,
|
||||
// but with a toString() method to help dojo/store/JsonRest.
|
||||
// Search string like "Co*" converted to regex like /^Co.*$/i.
|
||||
q = filter.patternToRegExp(qs, this.ignoreCase);
|
||||
q.toString = function(){ return qs; };
|
||||
}
|
||||
|
||||
// set _lastQuery, *then* start the timeout
|
||||
// otherwise, if the user types and the last query returns before the timeout,
|
||||
// _lastQuery won't be set and their input gets rewritten
|
||||
this._lastQuery = query[this.searchAttr] = q;
|
||||
this._queryDeferHandle = this.defer(startQuery, this.searchDelay);
|
||||
},
|
||||
|
||||
//////////// INITIALIZATION METHODS ///////////////////////////////////////
|
||||
|
||||
constructor: function(){
|
||||
this.query={};
|
||||
this.fetchProperties={};
|
||||
},
|
||||
|
||||
postMixInProperties: function(){
|
||||
if(!this.store){
|
||||
var list = this.list;
|
||||
if(list){
|
||||
this.store = registry.byId(list);
|
||||
}
|
||||
}
|
||||
this.inherited(arguments);
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user