123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- define("dojox/mobile/ComboBox", [
- "dojo/_base/kernel",
- "dojo/_base/declare",
- "dojo/_base/lang",
- "dojo/_base/window",
- "dojo/dom-geometry",
- "dojo/dom-style",
- "dojo/window",
- "dijit/form/_AutoCompleterMixin",
- "dijit/popup",
- "./_ComboBoxMenu",
- "./TextBox",
- "./sniff"
- ], function(kernel, declare, lang, win, domGeometry, domStyle, windowUtils, AutoCompleterMixin, popup, ComboBoxMenu, TextBox, has){
- kernel.experimental("dojox.mobile.ComboBox"); // should be using a more native search-type UI
- /*=====
- TextBox = dojox.mobile.TextBox;
- AutoCompleterMixin = dijit.form._AutoCompleterMixin;
- =====*/
- return declare("dojox.mobile.ComboBox", [TextBox, AutoCompleterMixin], {
- // summary:
- // A non-templated auto-completing text box widget
- //
- // dropDownClass: [protected extension] String
- // Name of the dropdown widget class used to select a date/time.
- // Subclasses should specify this.
- dropDownClass: "dojox.mobile._ComboBoxMenu",
- // initially disable selection since iphone displays selection handles that makes it hard to pick from the list
- selectOnClick: false,
- autoComplete: false,
- // dropDown: [protected] Widget
- // The widget to display as a popup. This widget *must* be
- // defined before the startup function is called.
- dropDown: null,
- // maxHeight: [protected] Integer
- // The max height for our dropdown.
- // Any dropdown taller than this will have scrollbars.
- // Set to -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"],
- _throttleOpenClose: function(){
- // prevent open/close in rapid succession
- if(this._throttleHandler){
- clearTimeout(this._throttleHandler);
- }
- this._throttleHandler = setTimeout(lang.hitch(this, function(){ this._throttleHandler = null; }), 500);
- },
- _onFocus: function(){
- this.inherited(arguments);
- if(!this._opened && !this._throttleHandler){
- this._startSearchAll(); // show dropdown if user is selecting Next/Previous from virtual keyboard
- }
- },
- onInput: function(e){
- this._onKey(e);
- this.inherited(arguments);
- },
- _setListAttr: function(v){
- this._set('list', v); // needed for Firefox 4+ to prevent HTML5 mode
- },
- closeDropDown: function(){
- // summary:
- // Closes the drop down on this widget
- // tags:
- // protected
- this._throttleOpenClose();
- if(this.startHandler){
- this.disconnect(this.startHandler);
- this.startHandler = null;
- if(this.moveHandler){ this.disconnect(this.moveHandler); }
- if(this.endHandler){ this.disconnect(this.endHandler); }
- }
- this.inherited(arguments);
- popup.close(this.dropDown);
- this._opened = false;
- },
- openDropDown: function(){
- // summary:
- // Opens the dropdown for this widget. To be called only when this.dropDown
- // has been created and is ready to display (ie, it's data is loaded).
- // returns:
- // return value of popup.open()
- // tags:
- // protected
- var wasClosed = !this._opened;
- var dropDown = this.dropDown,
- ddNode = dropDown.domNode,
- aroundNode = this.domNode,
- self = this;
- // TODO: isn't maxHeight dependent on the return value from popup.open(),
- // ie, dependent on how much space is available (BK)
- if(!this._preparedNode){
- this._preparedNode = true;
- // Check if we have explicitly set width and height on the dropdown widget dom node
- if(ddNode.style.width){
- this._explicitDDWidth = true;
- }
- if(ddNode.style.height){
- this._explicitDDHeight = true;
- }
- }
- // Code for resizing dropdown (height limitation, or increasing width to match my width)
- var myStyle = {
- display: "",
- overflow: "hidden",
- visibility: "hidden"
- };
- if(!this._explicitDDWidth){
- myStyle.width = "";
- }
- if(!this._explicitDDHeight){
- myStyle.height = "";
- }
- domStyle.set(ddNode, myStyle);
- // Figure out maximum height allowed (if there is a height restriction)
- var maxHeight = this.maxHeight;
- if(maxHeight == -1){
- // limit height to space available in viewport either above or below my domNode
- // (whichever side has more room)
- var viewport = windowUtils.getBox(),
- position = domGeometry.position(aroundNode, false);
- maxHeight = Math.floor(Math.max(position.y, viewport.h - (position.y + position.h)));
- }
- // Attach dropDown to DOM and make make visibility:hidden rather than display:none
- // so we call startup() and also get the size
- popup.moveOffScreen(dropDown);
- if(dropDown.startup && !dropDown._started){
- dropDown.startup(); // this has to be done after being added to the DOM
- }
- // Get size of drop down, and determine if vertical scroll bar needed
- var mb = domGeometry.position(this.dropDown.containerNode, false);
- var overHeight = (maxHeight && mb.h > maxHeight);
- if(overHeight){
- mb.h = maxHeight;
- }
- // Adjust dropdown width to match or be larger than my width
- mb.w = Math.max(mb.w, aroundNode.offsetWidth);
- domGeometry.setMarginBox(ddNode, mb);
- var retVal = popup.open({
- parent: this,
- popup: dropDown,
- around: aroundNode,
- orient: this.dropDownPosition,
- onExecute: function(){
- self.closeDropDown();
- },
- onCancel: function(){
- self.closeDropDown();
- },
- onClose: function(){
- self._opened = false;
- }
- });
- this._opened=true;
- if(wasClosed){
- if(retVal.aroundCorner.charAt(0) == 'B'){ // is popup below?
- this.domNode.scrollIntoView(true); // scroll to top
- }
- this.startHandler = this.connect(win.doc.documentElement, has("touch") ? "ontouchstart" : "onmousedown",
- lang.hitch(this, function(){
- var isMove = false;
- this.moveHandler = this.connect(win.doc.documentElement, has("touch") ? "ontouchmove" : "onmousemove", function(){ isMove = true; });
- this.endHandler = this.connect(win.doc.documentElement, has("touch") ? "ontouchend" : "onmouseup", function(){ if(!isMove){ this.closeDropDown(); } });
- })
- );
- }
- return retVal;
- },
- postCreate: function(){
- this.inherited(arguments);
- this.connect(this.domNode, "onclick", "_onClick");
- },
- _onClick: function(/*Event*/ e){
- // throttle clicks to prevent double click from doing double actions
- if(!this._throttleHandler){
- if(this.opened){
- this.closeDropDown();
- }else{
- this._startSearchAll();
- }
- }
- }
- });
- });
|