+ // private
+ onLoadException : function()
+ {
+ this.hasQuery = false;
+
+ if(typeof(this.loading) !== 'undefined' && this.loading !== null){
+ this.loading.hide();
+ }
+
+ if(this.tickable && this.editable){
+ return;
+ }
+
+ this.collapse();
+ // only causes errors at present
+ //Roo.log(this.store.reader.jsonData);
+ //if (this.store && typeof(this.store.reader.jsonData.errorMsg) != 'undefined') {
+ // fixme
+ //Roo.MessageBox.alert("Error loading",this.store.reader.jsonData.errorMsg);
+ //}
+
+
+ },
+ // private
+ onTypeAhead : function(){
+ if(this.store.getCount() > 0){
+ var r = this.store.getAt(0);
+ var newValue = r.data[this.displayField];
+ var len = newValue.length;
+ var selStart = this.getRawValue().length;
+
+ if(selStart != len){
+ this.setRawValue(newValue);
+ this.selectText(selStart, newValue.length);
+ }
+ }
+ },
+
+ // private
+ onSelect : function(record, index){
+
+ if(this.fireEvent('beforeselect', this, record, index) !== false){
+
+ this.setFromData(index > -1 ? record.data : false);
+
+ this.collapse();
+ this.fireEvent('select', this, record, index);
+ }
+ },
+
+ /**
+ * Returns the currently selected field value or empty string if no value is set.
+ * @return {String} value The selected value
+ */
+ getValue : function()
+ {
+ if(Roo.isIOS && this.useNativeIOS){
+ return this.ios_options[this.inputEl().dom.selectedIndex].data[this.valueField];
+ }
+
+ if(this.multiple){
+ return (this.hiddenField) ? this.hiddenField.dom.value : this.value;
+ }
+
+ if(this.valueField){
+ return typeof this.value != 'undefined' ? this.value : '';
+ }else{
+ return Roo.bootstrap.form.ComboBox.superclass.getValue.call(this);
+ }
+ },
+
+ getRawValue : function()
+ {
+ if(Roo.isIOS && this.useNativeIOS){
+ return this.ios_options[this.inputEl().dom.selectedIndex].data[this.displayField];
+ }
+
+ var v = this.inputEl().getValue();
+
+ return v;
+ },
+
+ /**
+ * Clears any text/value currently set in the field
+ */
+ clearValue : function(){
+
+ if(this.hiddenField){
+ this.hiddenField.dom.value = '';
+ }
+ this.value = '';
+ this.setRawValue('');
+ this.lastSelectionText = '';
+ this.lastData = false;
+
+ var close = this.closeTriggerEl();
+
+ if(close){
+ close.hide();
+ }
+
+ this.validate();
+
+ },
+
+ /**
+ * Sets the specified value into the field. If the value finds a match, the corresponding record text
+ * will be displayed in the field. If the value does not match the data value of an existing item,
+ * and the valueNotFoundText config option is defined, it will be displayed as the default field text.
+ * Otherwise the field will be blank (although the value will still be set).
+ * @param {String} value The value to match
+ */
+ setValue : function(v)
+ {
+ if(Roo.isIOS && this.useNativeIOS){
+ this.setIOSValue(v);
+ return;
+ }
+
+ if(this.multiple){
+ this.syncValue();
+ return;
+ }
+
+ var text = v;
+ if(this.valueField){
+ var r = this.findRecord(this.valueField, v);
+ if(r){
+ text = r.data[this.displayField];
+ }else if(this.valueNotFoundText !== undefined){
+ text = this.valueNotFoundText;
+ }
+ }
+ this.lastSelectionText = text;
+ if(this.hiddenField){
+ this.hiddenField.dom.value = v;
+ }
+ Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, text);
+ this.value = v;
+
+ var close = this.closeTriggerEl();
+
+ if(close){
+ (v && (v.length || v * 1 > 0)) ? close.show() : close.hide();
+ }
+
+ this.validate();
+ },
+ /**
+ * @property {Object} the last set data for the element
+ */
+
+ lastData : false,
+ /**
+ * Sets the value of the field based on a object which is related to the record format for the store.
+ * @param {Object} value the value to set as. or false on reset?
+ */
+ setFromData : function(o){
+
+ if(this.multiple){
+ this.addItem(o);
+ return;
+ }
+
+ var dv = ''; // display value
+ var vv = ''; // value value..
+ this.lastData = o;
+ if (this.displayField) {
+ dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
+ } else {
+ // this is an error condition!!!
+ Roo.log('no displayField value set for '+ (this.name ? this.name : this.id));
+ }
+
+ if(this.valueField){
+ vv = !o || typeof(o[this.valueField]) == 'undefined' ? dv : o[this.valueField];
+ }
+
+ var close = this.closeTriggerEl();
+
+ if(close){
+ if(dv.length || vv * 1 > 0){
+ close.show() ;
+ this.blockFocus=true;
+ } else {
+ close.hide();
+ }
+ }
+
+ if(this.hiddenField){
+ this.hiddenField.dom.value = vv;
+
+ this.lastSelectionText = dv;
+ Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, dv);
+ this.value = vv;
+ return;
+ }
+ // no hidden field.. - we store the value in 'value', but still display
+ // display field!!!!
+ this.lastSelectionText = dv;
+ Roo.bootstrap.form.ComboBox.superclass.setValue.call(this, dv);
+ this.value = vv;
+
+
+
+ },
+ // private
+ reset : function(){
+ // overridden so that last data is reset..
+
+ if(this.multiple){
+ this.clearItem();
+ return;
+ }
+
+ this.setValue(this.originalValue);
+ //this.clearInvalid();
+ this.lastData = false;
+ if (this.view) {
+ this.view.clearSelections();
+ }
+
+ this.validate();
+ },
+ // private
+ findRecord : function(prop, value){
+ var record;
+ if(this.store.getCount() > 0){
+ this.store.each(function(r){
+ if(r.data[prop] == value){
+ record = r;
+ return false;
+ }
+ return true;
+ });
+ }
+ return record;
+ },
+
+ getName: function()
+ {
+ // returns hidden if it's set..
+ if (!this.rendered) {return ''};
+ return !this.hiddenName && this.inputEl().dom.name ? this.inputEl().dom.name : (this.hiddenName || '');
+
+ },
+ // private
+ onViewMove : function(e, t){
+ this.inKeyMode = false;
+ },
+
+ // private
+ onViewOver : function(e, t){
+ if(this.inKeyMode){ // prevent key nav and mouse over conflicts
+ return;
+ }
+ var item = this.view.findItemFromChild(t);
+
+ if(item){
+ var index = this.view.indexOf(item);
+ this.select(index, false);
+ }
+ },
+
+ // private
+ onViewClick : function(view, doFocus, el, e)
+ {
+ var index = this.view.getSelectedIndexes()[0];
+
+ var r = this.store.getAt(index);
+
+ if(this.tickable){
+
+ if(typeof(e) != 'undefined' && e.getTarget().nodeName.toLowerCase() != 'input'){
+ return;
+ }
+
+ var rm = false;
+ var _this = this;
+
+ Roo.each(this.tickItems, function(v,k){
+
+ if(typeof(v) != 'undefined' && v[_this.valueField] == r.data[_this.valueField]){
+ Roo.log(v);
+ _this.tickItems.splice(k, 1);
+
+ if(typeof(e) == 'undefined' && view == false){
+ Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked = false;
+ }
+
+ rm = true;
+ return;
+ }
+ });
+
+ if(rm){
+ return;
+ }
+
+ if(this.fireEvent('tick', this, r, index, Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked) !== false){
+ this.tickItems.push(r.data);
+ }
+
+ if(typeof(e) == 'undefined' && view == false){
+ Roo.get(_this.view.getNodes(index, index)[0]).select('input', true).first().dom.checked = true;
+ }
+
+ return;
+ }
+
+ if(r){
+ this.onSelect(r, index);
+ }
+ if(doFocus !== false && !this.blockFocus){
+ this.inputEl().focus();
+ }
+ },
+
+ // private
+ restrictHeight : function(){
+ //this.innerList.dom.style.height = '';
+ //var inner = this.innerList.dom;
+ //var h = Math.max(inner.clientHeight, inner.offsetHeight, inner.scrollHeight);
+ //this.innerList.setHeight(h < this.maxHeight ? 'auto' : this.maxHeight);
+ //this.list.beginUpdate();
+ //this.list.setHeight(this.innerList.getHeight()+this.list.getFrameWidth('tb')+(this.resizable?this.handleHeight:0)+this.assetHeight);
+ this.list.alignTo(this.inputEl(), this.listAlign);
+ this.list.alignTo(this.inputEl(), this.listAlign);
+ //this.list.endUpdate();
+ },
+
+ // private
+ onEmptyResults : function(){
+
+ if(this.tickable && this.editable){
+ this.hasFocus = false;
+ this.restrictHeight();
+ return;
+ }
+
+ this.collapse();
+ },
+
+ /**
+ * Returns true if the dropdown list is expanded, else false.
+ */
+ isExpanded : function(){
+ return this.list.isVisible();
+ },
+
+ /**
+ * Select an item in the dropdown list by its data value. This function does NOT cause the select event to fire.
+ * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
+ * @param {String} value The data value of the item to select
+ * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
+ * selected item if it is not currently in view (defaults to true)
+ * @return {Boolean} True if the value matched an item in the list, else false
+ */
+ selectByValue : function(v, scrollIntoView){
+ if(v !== undefined && v !== null){
+ var r = this.findRecord(this.valueField || this.displayField, v);
+ if(r){
+ this.select(this.store.indexOf(r), scrollIntoView);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Select an item in the dropdown list by its numeric index in the list. This function does NOT cause the select event to fire.
+ * The store must be loaded and the list expanded for this function to work, otherwise use setValue.
+ * @param {Number} index The zero-based index of the list item to select
+ * @param {Boolean} scrollIntoView False to prevent the dropdown list from autoscrolling to display the
+ * selected item if it is not currently in view (defaults to true)
+ */
+ select : function(index, scrollIntoView){
+ this.selectedIndex = index;
+ this.view.select(index);
+ if(scrollIntoView !== false){
+ var el = this.view.getNode(index);
+ /*
+ * el && !this.multiple && !this.tickable // not sure why we disable multiple before..
+ */
+ if(el){
+ this.list.scrollChildIntoView(el, false);
+ }
+ }
+ },
+
+ // private
+ selectNext : function(){
+ var ct = this.store.getCount();
+ if(ct > 0){
+ if(this.selectedIndex == -1){
+ this.select(0);
+ }else if(this.selectedIndex < ct-1){
+ this.select(this.selectedIndex+1);
+ }
+ }
+ },
+
+ // private
+ selectPrev : function(){
+ var ct = this.store.getCount();
+ if(ct > 0){
+ if(this.selectedIndex == -1){
+ this.select(0);
+ }else if(this.selectedIndex != 0){
+ this.select(this.selectedIndex-1);
+ }
+ }
+ },
+
+ // private
+ onKeyUp : function(e){
+ if(this.editable !== false && !e.isSpecialKey()){
+ this.lastKey = e.getKey();
+ this.dqTask.delay(this.queryDelay);
+ }
+ },
+
+ // private
+ validateBlur : function(){
+ return !this.list || !this.list.isVisible();
+ },
+
+ // private
+ initQuery : function(){
+
+ var v = this.getRawValue();
+
+ if(this.tickable && this.editable){
+ v = this.tickableInputEl().getValue();
+ }
+
+ this.doQuery(v);
+ },
+
+ // private
+ doForce : function(){
+ if(this.inputEl().dom.value.length > 0){
+ this.inputEl().dom.value =
+ this.lastSelectionText === undefined ? '' : this.lastSelectionText;
+
+ }
+ },
+
+ /**
+ * Execute a query to filter the dropdown list. Fires the beforequery event prior to performing the
+ * query allowing the query action to be canceled if needed.
+ * @param {String} query The SQL query to execute
+ * @param {Boolean} forceAll True to force the query to execute even if there are currently fewer characters
+ * in the field than the minimum specified by the minChars config option. It also clears any filter previously
+ * saved in the current store (defaults to false)
+ */
+ doQuery : function(q, forceAll){
+
+ if(q === undefined || q === null){
+ q = '';
+ }
+ var qe = {
+ query: q,
+ forceAll: forceAll,
+ combo: this,
+ cancel:false
+ };
+ if(this.fireEvent('beforequery', qe)===false || qe.cancel){
+ return false;
+ }
+ q = qe.query;
+
+ forceAll = qe.forceAll;
+ if(forceAll === true || (q.length >= this.minChars)){
+
+ this.hasQuery = true;
+
+ if(this.lastQuery != q || this.alwaysQuery){
+ this.lastQuery = q;
+ if(this.mode == 'local'){
+ this.selectedIndex = -1;
+ if(forceAll){
+ this.store.clearFilter();
+ }else{
+
+ if(this.specialFilter){
+ this.fireEvent('specialfilter', this);
+ this.onLoad();
+ return;
+ }
+
+ this.store.filter(this.displayField, q);
+ }
+
+ this.store.fireEvent("datachanged", this.store);
+
+ this.onLoad();
+
+
+ }else{
+
+ this.store.baseParams[this.queryParam] = q;
+
+ var options = {params : this.getParams(q)};
+
+ if(this.loadNext){
+ options.add = true;
+ options.params.start = this.page * this.pageSize;
+ }
+
+ this.store.load(options);
+
+ /*
+ * this code will make the page width larger, at the beginning, the list not align correctly,
+ * we should expand the list on onLoad
+ * so command out it
+ */
+// this.expand();
+ }
+ }else{
+ this.selectedIndex = -1;
+ this.onLoad();
+ }
+ }
+
+ this.loadNext = false;
+ },
+
+ // private
+ getParams : function(q){
+ var p = {};
+ //p[this.queryParam] = q;
+
+ if(this.pageSize){
+ p.start = 0;
+ p.limit = this.pageSize;
+ }
+ return p;
+ },
+
+ /**
+ * Hides the dropdown list if it is currently expanded. Fires the 'collapse' event on completion.
+ */
+ collapse : function(){
+ if(!this.isExpanded()){
+ return;
+ }
+
+ this.list.hide();
+
+ this.hasFocus = false;
+
+ if(this.tickable){
+ this.okBtn.hide();
+ this.cancelBtn.hide();
+ this.trigger.show();
+
+ if(this.editable){
+ this.tickableInputEl().dom.value = '';
+ this.tickableInputEl().blur();
+ }
+
+ }
+
+ Roo.get(document).un('mousedown', this.collapseIf, this);
+ Roo.get(document).un('mousewheel', this.collapseIf, this);
+ if (!this.editable) {
+ Roo.get(document).un('keydown', this.listKeyPress, this);
+ }
+ this.fireEvent('collapse', this);
+
+ this.validate();
+ },
+
+ // private
+ collapseIf : function(e){
+ var in_combo = e.within(this.el);
+ var in_list = e.within(this.list);
+ var is_list = (Roo.get(e.getTarget()).id == this.list.id) ? true : false;
+
+ if (in_combo || in_list || is_list) {
+ //e.stopPropagation();
+ return;
+ }
+
+ if(this.tickable){
+ this.onTickableFooterButtonClick(e, false, false);
+ }
+
+ this.collapse();
+
+ },
+
+ /**
+ * Expands the dropdown list if it is currently hidden. Fires the 'expand' event on completion.
+ */
+ expand : function(){
+
+ if(this.isExpanded() || !this.hasFocus){
+ return;
+ }
+
+ var lw = this.listWidth || Math.max(this.inputEl().getWidth(), this.minListWidth);
+ this.list.setWidth(lw);
+
+ Roo.log('expand');
+
+ this.list.show();
+
+ this.restrictHeight();
+
+ if(this.tickable){
+
+ this.tickItems = Roo.apply([], this.item);
+
+ this.okBtn.show();
+ this.cancelBtn.show();
+ this.trigger.hide();
+
+ if(this.editable){
+ this.tickableInputEl().focus();
+ }
+
+ }
+
+ Roo.get(document).on('mousedown', this.collapseIf, this);
+ Roo.get(document).on('mousewheel', this.collapseIf, this);
+ if (!this.editable) {
+ Roo.get(document).on('keydown', this.listKeyPress, this);
+ }
+
+ this.fireEvent('expand', this);
+ },
+
+ // private
+ // Implements the default empty TriggerField.onTriggerClick function
+ onTriggerClick : function(e)
+ {
+ Roo.log('trigger click');
+
+ if(this.disabled || !this.triggerList){
+ return;
+ }
+
+ this.page = 0;
+ this.loadNext = false;
+
+ if(this.isExpanded()){
+ this.collapse();
+ if (!this.blockFocus) {
+ this.inputEl().focus();
+ }
+
+ }else {
+ this.hasFocus = true;
+ if(this.triggerAction == 'all') {
+ this.doQuery(this.allQuery, true);
+ } else {
+ this.doQuery(this.getRawValue());
+ }
+ if (!this.blockFocus) {
+ this.inputEl().focus();
+ }
+ }
+ },
+
+ onTickableTriggerClick : function(e)
+ {
+ if(this.disabled){
+ return;
+ }
+
+ this.page = 0;
+ this.loadNext = false;
+ this.hasFocus = true;
+
+ if(this.triggerAction == 'all') {
+ this.doQuery(this.allQuery, true);
+ } else {
+ this.doQuery(this.getRawValue());
+ }
+ },
+
+ onSearchFieldClick : function(e)
+ {
+ if(this.hasFocus && !this.disabled && e.getTarget().nodeName.toLowerCase() != 'button'){
+ this.onTickableFooterButtonClick(e, false, false);
+ return;
+ }
+
+ if(this.hasFocus || this.disabled || e.getTarget().nodeName.toLowerCase() == 'button'){
+ return;
+ }
+
+ this.page = 0;
+ this.loadNext = false;
+ this.hasFocus = true;
+
+ if(this.triggerAction == 'all') {
+ this.doQuery(this.allQuery, true);
+ } else {
+ this.doQuery(this.getRawValue());
+ }
+ },
+
+ listKeyPress : function(e)
+ {
+ //Roo.log('listkeypress');
+ // scroll to first matching element based on key pres..
+ if (e.isSpecialKey()) {
+ return false;
+ }
+ var k = String.fromCharCode(e.getKey()).toUpperCase();
+ //Roo.log(k);
+ var match = false;
+ var csel = this.view.getSelectedNodes();
+ var cselitem = false;
+ if (csel.length) {
+ var ix = this.view.indexOf(csel[0]);
+ cselitem = this.store.getAt(ix);
+ if (!cselitem.get(this.displayField) || cselitem.get(this.displayField).substring(0,1).toUpperCase() != k) {
+ cselitem = false;
+ }
+
+ }
+
+ this.store.each(function(v) {
+ if (cselitem) {
+ // start at existing selection.
+ if (cselitem.id == v.id) {
+ cselitem = false;
+ }
+ return true;
+ }
+
+ if (v.get(this.displayField) && v.get(this.displayField).substring(0,1).toUpperCase() == k) {
+ match = this.store.indexOf(v);
+ return false;
+ }
+ return true;
+ }, this);
+
+ if (match === false) {
+ return true; // no more action?
+ }
+ // scroll to?
+ this.view.select(match);
+ var sn = Roo.get(this.view.getSelectedNodes()[0]);
+ sn.scrollIntoView(sn.dom.parentNode, false);
+ },
+
+ onViewScroll : function(e, t){
+
+ if(this.view.el.getScroll().top == 0 ||this.view.el.getScroll().top < this.view.el.dom.scrollHeight - this.view.el.dom.clientHeight || !this.hasFocus || !this.append || this.hasQuery){
+ return;
+ }
+
+ this.hasQuery = true;
+
+ this.loading = this.list.select('.loading', true).first();
+
+ if(this.loading === null){
+ this.list.createChild({
+ tag: 'div',
+ cls: 'loading roo-select2-more-results roo-select2-active',
+ html: 'Loading more results...'
+ });
+
+ this.loading = this.list.select('.loading', true).first();
+
+ this.loading.setVisibilityMode(Roo.Element.DISPLAY);
+
+ this.loading.hide();
+ }
+
+ this.loading.show();
+
+ var _combo = this;
+
+ this.page++;
+ this.loadNext = true;
+
+ (function() { _combo.doQuery(_combo.allQuery, true); }).defer(500);
+
+ return;
+ },
+
+ addItem : function(o)
+ {
+ var dv = ''; // display value
+
+ if (this.displayField) {
+ dv = !o || typeof(o[this.displayField]) == 'undefined' ? '' : o[this.displayField];
+ } else {
+ // this is an error condition!!!
+ Roo.log('no displayField value set for '+ (this.name ? this.name : this.id));
+ }
+
+ if(!dv.length){
+ return;
+ }
+
+ var choice = this.choices.createChild({
+ tag: 'li',
+ cls: 'roo-select2-search-choice',
+ cn: [
+ {
+ tag: 'div',
+ html: dv
+ },
+ {
+ tag: 'a',
+ href: '#',
+ cls: 'roo-select2-search-choice-close fa fa-times',
+ tabindex: '-1'
+ }
+ ]
+
+ }, this.searchField);
+
+ var close = choice.select('a.roo-select2-search-choice-close', true).first();
+
+ close.on('click', this.onRemoveItem, this, { item : choice, data : o} );
+
+ this.item.push(o);
+
+ this.lastData = o;
+
+ this.syncValue();
+
+ this.inputEl().dom.value = '';
+
+ this.validate();
+ },
+
+ onRemoveItem : function(e, _self, o)
+ {
+ e.preventDefault();
+
+ this.lastItem = Roo.apply([], this.item);
+
+ var index = this.item.indexOf(o.data) * 1;
+
+ if( index < 0){
+ Roo.log('not this item?!');
+ return;
+ }
+
+ this.item.splice(index, 1);
+ o.item.remove();
+
+ this.syncValue();
+
+ this.fireEvent('remove', this, e);
+
+ this.validate();
+
+ },
+
+ syncValue : function()
+ {
+ if(!this.item.length){
+ this.clearValue();
+ return;
+ }
+
+ var value = [];
+ var _this = this;
+ Roo.each(this.item, function(i){
+ if(_this.valueField){
+ value.push(i[_this.valueField]);
+ return;
+ }
+
+ value.push(i);
+ });
+
+ this.value = value.join(',');
+
+ if(this.hiddenField){
+ this.hiddenField.dom.value = this.value;
+ }
+
+ this.store.fireEvent("datachanged", this.store);
+
+ this.validate();
+ },
+
+ clearItem : function()
+ {
+ if(!this.multiple){
+ return;
+ }
+
+ this.item = [];
+
+ Roo.each(this.choices.select('>li.roo-select2-search-choice', true).elements, function(c){
+ c.remove();
+ });
+
+ this.syncValue();
+
+ this.validate();
+
+ if(this.tickable && !Roo.isTouch){
+ this.view.refresh();
+ }
+ },
+
+ inputEl: function ()
+ {
+ if(Roo.isIOS && this.useNativeIOS){
+ return this.el.select('select.roo-ios-select', true).first();
+ }
+
+ if(Roo.isTouch && this.mobileTouchView){
+ return this.el.select('input.form-control',true).first();
+ }
+
+ if(this.tickable){
+ return this.searchField;
+ }
+
+ return this.el.select('input.form-control',true).first();
+ },
+
+ onTickableFooterButtonClick : function(e, btn, el)
+ {
+ e.preventDefault();
+
+ this.lastItem = Roo.apply([], this.item);
+
+ if(btn && btn.name == 'cancel'){
+ this.tickItems = Roo.apply([], this.item);
+ this.collapse();
+ return;
+ }
+
+ this.clearItem();
+
+ var _this = this;
+
+ Roo.each(this.tickItems, function(o){
+ _this.addItem(o);
+ });
+
+ this.collapse();
+
+ },
+
+ validate : function()
+ {
+ if(this.getVisibilityEl().hasClass('hidden')){
+ return true;
+ }
+
+ var v = this.getRawValue();
+
+ if(this.multiple){
+ v = this.getValue();
+ }
+
+ if(this.disabled || this.allowBlank || v.length){
+ this.markValid();
+ return true;
+ }
+
+ this.markInvalid();
+ return false;
+ },
+
+ tickableInputEl : function()
+ {
+ if(!this.tickable || !this.editable){
+ return this.inputEl();
+ }
+
+ return this.inputEl().select('.roo-select2-search-field-input', true).first();
+ },
+
+
+ getAutoCreateTouchView : function()
+ {
+ var id = Roo.id();
+
+ var cfg = {
+ cls: 'form-group' //input-group
+ };
+
+ var input = {
+ tag: 'input',
+ id : id,
+ type : this.inputType,
+ cls : 'form-control x-combo-noedit',
+ autocomplete: 'new-password',
+ placeholder : this.placeholder || '',
+ readonly : true
+ };
+
+ if (this.name) {
+ input.name = this.name;
+ }
+
+ if (this.size) {
+ input.cls += ' input-' + this.size;
+ }
+
+ if (this.disabled) {
+ input.disabled = true;
+ }
+
+ var inputblock = {
+ cls : 'roo-combobox-wrap',
+ cn : [
+ input
+ ]
+ };
+
+ if(this.before){
+ inputblock.cls += ' input-group';
+
+ inputblock.cn.unshift({
+ tag :'span',
+ cls : 'input-group-addon input-group-prepend input-group-text',
+ html : this.before
+ });
+ }
+
+ if(this.removable && !this.multiple){
+ inputblock.cls += ' roo-removable';
+
+ inputblock.cn.push({
+ tag: 'button',
+ html : 'x',
+ cls : 'roo-combo-removable-btn close'
+ });
+ }
+
+ if(this.hasFeedback && !this.allowBlank){
+
+ inputblock.cls += ' has-feedback';
+
+ inputblock.cn.push({
+ tag: 'span',
+ cls: 'glyphicon form-control-feedback'
+ });
+
+ }
+
+ if (this.after) {
+
+ inputblock.cls += (this.before) ? '' : ' input-group';
+
+ inputblock.cn.push({
+ tag :'span',
+ cls : 'input-group-addon input-group-append input-group-text',
+ html : this.after
+ });
+ }
+
+
+ var ibwrap = inputblock;
+
+ if(this.multiple){
+ ibwrap = {
+ tag: 'ul',
+ cls: 'roo-select2-choices',
+ cn:[
+ {
+ tag: 'li',
+ cls: 'roo-select2-search-field',
+ cn: [
+
+ inputblock
+ ]
+ }
+ ]
+ };
+
+
+ }
+
+ var combobox = {
+ cls: 'roo-select2-container input-group roo-touchview-combobox ',
+ cn: [
+ {
+ tag: 'input',
+ type : 'hidden',
+ cls: 'form-hidden-field'
+ },
+ ibwrap
+ ]
+ };
+
+ if(!this.multiple && this.showToggleBtn){
+
+ var caret = {
+ cls: 'caret'
+ };
+
+ if (this.caret != false) {
+ caret = {
+ tag: 'i',
+ cls: 'fa fa-' + this.caret
+ };
+
+ }
+
+ combobox.cn.push({
+ tag :'span',
+ cls : 'input-group-addon input-group-append input-group-text btn dropdown-toggle',
+ cn : [
+ Roo.bootstrap.version == 3 ? caret : '',
+ {
+ tag: 'span',
+ cls: 'combobox-clear',
+ cn : [
+ {
+ tag : 'i',
+ cls: 'icon-remove'
+ }
+ ]
+ }
+ ]
+
+ })
+ }
+
+ if(this.multiple){
+ combobox.cls += ' roo-select2-container-multi';
+ }
+
+ var required = this.allowBlank ? {
+ tag : 'i',
+ style: 'display: none'
+ } : {
+ tag : 'i',
+ cls : 'roo-required-indicator left-indicator text-danger fa fa-lg fa-star',
+ tooltip : 'This field is required'
+ };
+
+ var align = this.labelAlign || this.parentLabelAlign();
+
+ if (align ==='left' && this.fieldLabel.length) {
+
+ cfg.cn = [
+ required,
+ {
+ tag: 'label',
+ cls : 'control-label col-form-label',
+ html : this.fieldLabel
+
+ },
+ {
+ cls : 'roo-combobox-wrap ',
+ cn: [
+ combobox
+ ]
+ }
+ ];
+
+ var labelCfg = cfg.cn[1];
+ var contentCfg = cfg.cn[2];
+
+
+ if(this.indicatorpos == 'right'){
+ cfg.cn = [
+ {
+ tag: 'label',
+ 'for' : id,
+ cls : 'control-label col-form-label',
+ cn : [
+ {
+ tag : 'span',
+ html : this.fieldLabel
+ },
+ required
+ ]
+ },
+ {
+ cls : "roo-combobox-wrap ",
+ cn: [
+ combobox
+ ]
+ }
+
+ ];
+
+ labelCfg = cfg.cn[0];
+ contentCfg = cfg.cn[1];
+ }
+
+
+
+ if(this.labelWidth > 12){
+ labelCfg.style = "width: " + this.labelWidth + 'px';
+ }
+
+ if(this.labelWidth < 13 && this.labelmd == 0){
+ this.labelmd = this.labelWidth;
+ }
+
+ if(this.labellg > 0){
+ labelCfg.cls += ' col-lg-' + this.labellg;
+ contentCfg.cls += ' col-lg-' + (12 - this.labellg);
+ }
+
+ if(this.labelmd > 0){
+ labelCfg.cls += ' col-md-' + this.labelmd;
+ contentCfg.cls += ' col-md-' + (12 - this.labelmd);
+ }
+
+ if(this.labelsm > 0){
+ labelCfg.cls += ' col-sm-' + this.labelsm;
+ contentCfg.cls += ' col-sm-' + (12 - this.labelsm);
+ }
+
+ if(this.labelxs > 0){
+ labelCfg.cls += ' col-xs-' + this.labelxs;
+ contentCfg.cls += ' col-xs-' + (12 - this.labelxs);
+ }
+
+
+ } else if ( this.fieldLabel.length) {
+ cfg.cn = [
+ required,
+ {
+ tag: 'label',
+ cls : 'control-label',
+ html : this.fieldLabel
+
+ },
+ {
+ cls : '',
+ cn: [
+ combobox
+ ]
+ }
+ ];
+
+ if(this.indicatorpos == 'right'){
+ cfg.cn = [
+ {
+ tag: 'label',
+ cls : 'control-label',
+ html : this.fieldLabel,
+ cn : [
+ required
+ ]
+ },
+ {
+ cls : '',
+ cn: [
+ combobox
+ ]
+ }
+ ];
+ }
+ } else {
+ cfg.cn = combobox;
+ }
+
+
+ var settings = this;
+
+ ['xs','sm','md','lg'].map(function(size){
+ if (settings[size]) {
+ cfg.cls += ' col-' + size + '-' + settings[size];
+ }
+ });
+
+ return cfg;
+ },
+
+ initTouchView : function()
+ {
+ this.renderTouchView();
+
+ this.touchViewEl.on('scroll', function(){
+ this.el.dom.scrollTop = 0;
+ }, this);
+
+ this.originalValue = this.getValue();
+
+ this.triggerEl = this.el.select('span.dropdown-toggle',true).first();
+
+ this.inputEl().on("click", this.showTouchView, this);
+ if (this.triggerEl) {
+ this.triggerEl.on("click", this.showTouchView, this);
+ }
+
+
+ this.touchViewFooterEl.select('.roo-touch-view-cancel', true).first().on('click', this.hideTouchView, this);
+ this.touchViewFooterEl.select('.roo-touch-view-ok', true).first().on('click', this.setTouchViewValue, this);
+
+ this.maskEl = new Roo.LoadMask(this.touchViewEl, { store : this.store, msgCls: 'roo-el-mask-msg' });
+
+ this.store.on('beforeload', this.onTouchViewBeforeLoad, this);
+ this.store.on('load', this.onTouchViewLoad, this);
+ this.store.on('loadexception', this.onTouchViewLoadException, this);
+
+ if(this.hiddenName){
+
+ this.hiddenField = this.el.select('input.form-hidden-field',true).first();
+
+ this.hiddenField.dom.value =
+ this.hiddenValue !== undefined ? this.hiddenValue :
+ this.value !== undefined ? this.value : '';
+
+ this.el.dom.removeAttribute('name');
+ this.hiddenField.dom.setAttribute('name', this.hiddenName);
+ }
+
+ if(this.multiple){
+ this.choices = this.el.select('ul.roo-select2-choices', true).first();
+ this.searchField = this.el.select('ul li.roo-select2-search-field', true).first();
+ }
+
+ if(this.removable && !this.multiple){
+ var close = this.closeTriggerEl();
+ if(close){
+ close.setVisibilityMode(Roo.Element.DISPLAY).hide();
+ close.on('click', this.removeBtnClick, this, close);
+ }
+ }
+ /*
+ * fix the bug in Safari iOS8
+ */
+ this.inputEl().on("focus", function(e){
+ document.activeElement.blur();
+ }, this);
+
+ this._touchViewMask = Roo.DomHelper.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
+
+ return;
+
+
+ },
+
+ renderTouchView : function()
+ {
+ this.touchViewEl = Roo.get(document.body).createChild(Roo.bootstrap.form.ComboBox.touchViewTemplate);
+ this.touchViewEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.touchViewHeaderEl = this.touchViewEl.select('.modal-header', true).first();
+ this.touchViewHeaderEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.touchViewBodyEl = this.touchViewEl.select('.modal-body', true).first();
+ this.touchViewBodyEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+ this.touchViewBodyEl.setStyle('overflow', 'auto');
+
+ this.touchViewListGroup = this.touchViewBodyEl.select('.list-group', true).first();
+ this.touchViewListGroup.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ this.touchViewFooterEl = this.touchViewEl.select('.modal-footer', true).first();
+ this.touchViewFooterEl.setVisibilityMode(Roo.Element.DISPLAY).originalDisplay = 'block';
+
+ },
+
+ showTouchView : function()
+ {
+ if(this.disabled){
+ return;
+ }
+
+ this.touchViewHeaderEl.hide();
+
+ if(this.modalTitle.length){
+ this.touchViewHeaderEl.dom.innerHTML = this.modalTitle;
+ this.touchViewHeaderEl.show();
+ }
+
+ this.touchViewEl.setStyle('z-index', Roo.bootstrap.Modal.zIndex++);
+ this.touchViewEl.show();
+
+ this.touchViewEl.select('.modal-dialog', true).first().setStyle({ margin : '0px', width : '100%'});
+
+ //this.touchViewEl.select('.modal-dialog > .modal-content', true).first().setSize(
+ // Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
+
+ var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+ if(this.modalTitle.length){
+ bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+ }
+
+ this.touchViewBodyEl.setHeight(bodyHeight);
+
+ if(this.animate){
+ var _this = this;
+ (function(){ _this.touchViewEl.addClass(['in','show']); }).defer(50);
+ }else{
+ this.touchViewEl.addClass(['in','show']);
+ }
+
+ if(this._touchViewMask){
+ Roo.get(document.body).addClass("x-body-masked");
+ this._touchViewMask.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
+ this._touchViewMask.setStyle('z-index', 10000);
+ this._touchViewMask.addClass('show');
+ }
+
+ this.doTouchViewQuery();
+
+ },
+
+ hideTouchView : function()
+ {
+ this.touchViewEl.removeClass(['in','show']);
+
+ if(this.animate){
+ var _this = this;
+ (function(){ _this.touchViewEl.setStyle('display', 'none'); }).defer(150);
+ }else{
+ this.touchViewEl.setStyle('display', 'none');
+ }
+
+ if(this._touchViewMask){
+ this._touchViewMask.removeClass('show');
+ Roo.get(document.body).removeClass("x-body-masked");
+ }
+ },
+
+ setTouchViewValue : function()
+ {
+ if(this.multiple){
+ this.clearItem();
+
+ var _this = this;
+
+ Roo.each(this.tickItems, function(o){
+ this.addItem(o);
+ }, this);
+ }
+
+ this.hideTouchView();
+ },
+
+ doTouchViewQuery : function()
+ {
+ var qe = {
+ query: '',
+ forceAll: true,
+ combo: this,
+ cancel:false
+ };
+
+ if(this.fireEvent('beforequery', qe) ===false || qe.cancel){
+ return false;
+ }
+
+ if(!this.alwaysQuery || this.mode == 'local'){
+ this.onTouchViewLoad();
+ return;
+ }
+
+ this.store.load();
+ },
+
+ onTouchViewBeforeLoad : function(combo,opts)
+ {
+ return;
+ },
+
+ // private
+ onTouchViewLoad : function()
+ {
+ if(this.store.getCount() < 1){
+ this.onTouchViewEmptyResults();
+ return;
+ }
+
+ this.clearTouchView();
+
+ var rawValue = this.getRawValue();
+
+ var template = (this.multiple) ? Roo.bootstrap.form.ComboBox.listItemCheckbox : Roo.bootstrap.form.ComboBox.listItemRadio;
+
+ this.tickItems = [];
+
+ this.store.data.each(function(d, rowIndex){
+ var row = this.touchViewListGroup.createChild(template);
+
+ if(typeof(d.data.cls) != 'undefined' && d.data.cls.length){
+ row.addClass(d.data.cls);
+ }
+
+ if(this.displayField && typeof(d.data[this.displayField]) != 'undefined'){
+ var cfg = {
+ data : d.data,
+ html : d.data[this.displayField]
+ };
+
+ if(this.fireEvent('touchviewdisplay', this, cfg) !== false){
+ row.select('.roo-combobox-list-group-item-value', true).first().dom.innerHTML = cfg.html;
+ }
+ }
+ row.removeClass('selected');
+ if(!this.multiple && this.valueField &&
+ typeof(d.data[this.valueField]) != 'undefined' && d.data[this.valueField] == this.getValue())
+ {
+ // radio buttons..
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+ row.addClass('selected');
+ }
+
+ if(this.multiple && this.valueField &&
+ typeof(d.data[this.valueField]) != 'undefined' && this.getValue().indexOf(d.data[this.valueField]) != -1)
+ {
+
+ // checkboxes...
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+ this.tickItems.push(d.data);
+ }
+
+ row.on('click', this.onTouchViewClick, this, {row : row, rowIndex : rowIndex});
+
+ }, this);
+
+ var firstChecked = this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).first();
+
+ var bodyHeight = Roo.lib.Dom.getViewHeight() - this.touchViewFooterEl.getHeight() + this.touchViewBodyEl.getPadding('tb');
+
+ if(this.modalTitle.length){
+ bodyHeight = bodyHeight - this.touchViewHeaderEl.getHeight();
+ }
+
+ var listHeight = this.touchViewListGroup.getHeight() + this.touchViewBodyEl.getPadding('tb') * 2;
+
+ if(this.mobile_restrict_height && listHeight < bodyHeight){
+ this.touchViewBodyEl.setHeight(listHeight);
+ }
+
+ var _this = this;
+
+ if(firstChecked && listHeight > bodyHeight){
+ (function() { firstChecked.findParent('li').scrollIntoView(_this.touchViewListGroup.dom); }).defer(500);
+ }
+
+ },
+
+ onTouchViewLoadException : function()
+ {
+ this.hideTouchView();
+ },
+
+ onTouchViewEmptyResults : function()
+ {
+ this.clearTouchView();
+
+ this.touchViewListGroup.createChild(Roo.bootstrap.form.ComboBox.emptyResult);
+
+ this.touchViewListGroup.select('.roo-combobox-touch-view-empty-result', true).first().dom.innerHTML = this.emptyResultText;
+
+ },
+
+ clearTouchView : function()
+ {
+ this.touchViewListGroup.dom.innerHTML = '';
+ },
+
+ onTouchViewClick : function(e, el, o)
+ {
+ e.preventDefault();
+
+ var row = o.row;
+ var rowIndex = o.rowIndex;
+
+ var r = this.store.getAt(rowIndex);
+
+ if(this.fireEvent('beforeselect', this, r, rowIndex) !== false){
+
+ if(!this.multiple){
+ Roo.each(this.touchViewListGroup.select('.list-group-item > .roo-combobox-list-group-item-box > input:checked', true).elements, function(c){
+ c.dom.removeAttribute('checked');
+ }, this);
+
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+
+ this.setFromData(r.data);
+
+ var close = this.closeTriggerEl();
+
+ if(close){
+ close.show();
+ }
+
+ this.hideTouchView();
+
+ this.fireEvent('select', this, r, rowIndex);
+
+ return;
+ }
+
+ if(this.valueField && typeof(r.data[this.valueField]) != 'undefined' && this.getValue().indexOf(r.data[this.valueField]) != -1){
+ row.select('.roo-combobox-list-group-item-box > input', true).first().dom.removeAttribute('checked');
+ this.tickItems.splice(this.tickItems.indexOf(r.data), 1);
+ return;
+ }
+
+ row.select('.roo-combobox-list-group-item-box > input', true).first().attr('checked', true);
+ this.addItem(r.data);
+ this.tickItems.push(r.data);
+ }
+ },
+
+ getAutoCreateNativeIOS : function()
+ {
+ var cfg = {
+ cls: 'form-group' //input-group,
+ };
+
+ var combobox = {
+ tag: 'select',
+ cls : 'roo-ios-select'
+ };
+
+ if (this.name) {
+ combobox.name = this.name;
+ }
+
+ if (this.disabled) {
+ combobox.disabled = true;
+ }
+
+ var settings = this;
+
+ ['xs','sm','md','lg'].map(function(size){
+ if (settings[size]) {
+ cfg.cls += ' col-' + size + '-' + settings[size];
+ }
+ });
+
+ cfg.cn = combobox;
+
+ return cfg;
+
+ },
+
+ initIOSView : function()
+ {
+ this.store.on('load', this.onIOSViewLoad, this);
+
+ return;
+ },
+
+ onIOSViewLoad : function()
+ {
+ if(this.store.getCount() < 1){
+ return;
+ }
+
+ this.clearIOSView();
+
+ if(this.allowBlank) {
+
+ var default_text = '-- SELECT --';
+
+ if(this.placeholder.length){
+ default_text = this.placeholder;
+ }
+
+ if(this.emptyTitle.length){
+ default_text += ' - ' + this.emptyTitle + ' -';
+ }
+
+ var opt = this.inputEl().createChild({
+ tag: 'option',
+ value : 0,
+ html : default_text
+ });
+
+ var o = {};
+ o[this.valueField] = 0;
+ o[this.displayField] = default_text;
+
+ this.ios_options.push({
+ data : o,
+ el : opt
+ });
+
+ }
+
+ this.store.data.each(function(d, rowIndex){
+
+ var html = '';
+
+ if(this.displayField && typeof(d.data[this.displayField]) != 'undefined'){
+ html = d.data[this.displayField];
+ }
+
+ var value = '';
+
+ if(this.valueField && typeof(d.data[this.valueField]) != 'undefined'){
+ value = d.data[this.valueField];
+ }
+
+ var option = {
+ tag: 'option',
+ value : value,
+ html : html
+ };
+
+ if(this.value == d.data[this.valueField]){
+ option['selected'] = true;
+ }
+
+ var opt = this.inputEl().createChild(option);
+
+ this.ios_options.push({
+ data : d.data,
+ el : opt
+ });
+
+ }, this);
+
+ this.inputEl().on('change', function(){
+ this.fireEvent('select', this);
+ }, this);
+
+ },
+
+ clearIOSView: function()
+ {
+ this.inputEl().dom.innerHTML = '';
+
+ this.ios_options = [];
+ },
+
+ setIOSValue: function(v)
+ {
+ this.value = v;
+
+ if(!this.ios_options){
+ return;
+ }
+
+ Roo.each(this.ios_options, function(opts){
+
+ opts.el.dom.removeAttribute('selected');
+
+ if(opts.data[this.valueField] != v){
+ return;
+ }
+
+ opts.el.dom.setAttribute('selected', true);
+
+ }, this);
+ }
+
+ /**
+ * @cfg {Boolean} grow
+ * @hide
+ */
+ /**
+ * @cfg {Number} growMin
+ * @hide
+ */
+ /**
+ * @cfg {Number} growMax
+ * @hide
+ */
+ /**
+ * @hide
+ * @method autoSize
+ */
+});
+
+Roo.apply(Roo.bootstrap.form.ComboBox, {
+
+ header : {
+ tag: 'div',
+ cls: 'modal-header',
+ cn: [
+ {
+ tag: 'h4',
+ cls: 'modal-title'
+ }
+ ]
+ },
+
+ body : {
+ tag: 'div',
+ cls: 'modal-body',
+ cn: [
+ {
+ tag: 'ul',
+ cls: 'list-group'
+ }
+ ]
+ },
+
+ listItemRadio : {
+ tag: 'li',
+ cls: 'list-group-item',
+ cn: [
+ {
+ tag: 'span',
+ cls: 'roo-combobox-list-group-item-value'
+ },
+ {
+ tag: 'div',
+ cls: 'roo-combobox-list-group-item-box pull-xs-right radio-inline radio radio-info',
+ cn: [
+ {
+ tag: 'input',
+ type: 'radio'
+ },
+ {
+ tag: 'label'
+ }
+ ]
+ }
+ ]
+ },
+
+ listItemCheckbox : {
+ tag: 'li',
+ cls: 'list-group-item',
+ cn: [
+ {
+ tag: 'span',
+ cls: 'roo-combobox-list-group-item-value'
+ },
+ {
+ tag: 'div',
+ cls: 'roo-combobox-list-group-item-box pull-xs-right checkbox-inline checkbox checkbox-info',
+ cn: [
+ {
+ tag: 'input',
+ type: 'checkbox'
+ },
+ {
+ tag: 'label'
+ }
+ ]
+ }
+ ]
+ },
+
+ emptyResult : {
+ tag: 'div',
+ cls: 'alert alert-danger roo-combobox-touch-view-empty-result'
+ },
+
+ footer : {
+ tag: 'div',
+ cls: 'modal-footer',
+ cn: [
+ {
+ tag: 'div',
+ cls: 'row',
+ cn: [
+ {
+ tag: 'div',
+ cls: 'col-xs-6 text-left',
+ cn: {
+ tag: 'button',
+ cls: 'btn btn-danger roo-touch-view-cancel',
+ html: 'Cancel'
+ }
+ },
+ {
+ tag: 'div',
+ cls: 'col-xs-6 text-right',
+ cn: {
+ tag: 'button',
+ cls: 'btn btn-success roo-touch-view-ok',
+ html: 'OK'
+ }
+ }
+ ]
+ }
+ ]
+
+ }
+});
+
+Roo.apply(Roo.bootstrap.form.ComboBox, {
+
+ touchViewTemplate : {
+ tag: 'div',
+ cls: 'modal fade roo-combobox-touch-view',
+ cn: [
+ {
+ tag: 'div',
+ cls: 'modal-dialog',
+ style : 'position:fixed', // we have to fix position....
+ cn: [
+ {
+ tag: 'div',
+ cls: 'modal-content',
+ cn: [
+ Roo.bootstrap.form.ComboBox.header,
+ Roo.bootstrap.form.ComboBox.body,
+ Roo.bootstrap.form.ComboBox.footer
+ ]
+ }
+ ]
+ }
+ ]
+ }
+});/*
+ * Based on:
+ * Ext JS Library 1.1.1
+ * Copyright(c) 2006-2007, Ext JS, LLC.
+ *
+ * Originally Released Under LGPL - original licence link has changed is not relivant.
+ *
+ * Fork - LGPL
+ * <script type="text/javascript">
+ */
+
+/**
+ * @class Roo.View
+ * @extends Roo.util.Observable
+ * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template.
+ * This class also supports single and multi selection modes. <br>
+ * Create a data model bound view:
+ <pre><code>
+ var store = new Roo.data.Store(...);
+
+ var view = new Roo.View({
+ el : "my-element",
+ tpl : '<div id="{0}">{2} - {1}</div>', // auto create template
+
+ singleSelect: true,
+ selectedClass: "ydataview-selected",
+ store: store
+ });
+
+ // listen for node click?
+ view.on("click", function(vw, index, node, e){
+ alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
+ });
+
+ // load XML data
+ dataModel.load("foobar.xml");
+ </code></pre>
+ For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
+ * <br><br>
+ * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
+ * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
+ *
+ * Note: old style constructor is still suported (container, template, config)
+ *
+ * @constructor
+ * Create a new View
+ * @param {Object} config The config object
+ *
+ */
+Roo.View = function(config, depreciated_tpl, depreciated_config){
+
+ this.parent = false;
+
+ if (typeof(depreciated_tpl) == 'undefined') {
+ // new way.. - universal constructor.
+ Roo.apply(this, config);
+ this.el = Roo.get(this.el);
+ } else {
+ // old format..
+ this.el = Roo.get(config);
+ this.tpl = depreciated_tpl;
+ Roo.apply(this, depreciated_config);
+ }
+ this.wrapEl = this.el.wrap().wrap();
+ ///this.el = this.wrapEla.appendChild(document.createElement("div"));
+
+
+ if(typeof(this.tpl) == "string"){
+ this.tpl = new Roo.Template(this.tpl);
+ } else {
+ // support xtype ctors..
+ this.tpl = new Roo.factory(this.tpl, Roo);
+ }
+
+
+ this.tpl.compile();
+
+ /** @private */
+ this.addEvents({
+ /**
+ * @event beforeclick
+ * Fires before a click is processed. Returns false to cancel the default action.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "beforeclick" : true,
+ /**
+ * @event click
+ * Fires when a template node is clicked.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "click" : true,
+ /**
+ * @event dblclick
+ * Fires when a template node is double clicked.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "dblclick" : true,
+ /**
+ * @event contextmenu
+ * Fires when a template node is right clicked.
+ * @param {Roo.View} this
+ * @param {Number} index The index of the target node
+ * @param {HTMLElement} node The target node
+ * @param {Roo.EventObject} e The raw event object
+ */
+ "contextmenu" : true,
+ /**
+ * @event selectionchange
+ * Fires when the selected nodes change.
+ * @param {Roo.View} this
+ * @param {Array} selections Array of the selected nodes
+ */
+ "selectionchange" : true,
+
+ /**
+ * @event beforeselect
+ * Fires before a selection is made. If any handlers return false, the selection is cancelled.
+ * @param {Roo.View} this
+ * @param {HTMLElement} node The node to be selected
+ * @param {Array} selections Array of currently selected nodes
+ */
+ "beforeselect" : true,
+ /**
+ * @event preparedata
+ * Fires on every row to render, to allow you to change the data.
+ * @param {Roo.View} this
+ * @param {Object} data to be rendered (change this)
+ */
+ "preparedata" : true
+
+
+ });
+
+
+
+ this.el.on({
+ "click": this.onClick,
+ "dblclick": this.onDblClick,
+ "contextmenu": this.onContextMenu,
+ scope:this
+ });
+
+ this.selections = [];
+ this.nodes = [];
+ this.cmp = new Roo.CompositeElementLite([]);
+ if(this.store){
+ this.store = Roo.factory(this.store, Roo.data);
+ this.setStore(this.store, true);
+ }
+
+ if ( this.footer && this.footer.xtype) {
+
+ var fctr = this.wrapEl.appendChild(document.createElement("div"));
+
+ this.footer.dataSource = this.store;
+ this.footer.container = fctr;
+ this.footer = Roo.factory(this.footer, Roo);
+ fctr.insertFirst(this.el);
+
+ // this is a bit insane - as the paging toolbar seems to detach the el..
+// dom.parentNode.parentNode.parentNode
+ // they get detached?
+ }
+
+
+ Roo.View.superclass.constructor.call(this);
+
+
+};
+
+Roo.extend(Roo.View, Roo.util.Observable, {
+
+ /**
+ * @cfg {Roo.data.Store} store Data store to load data from.
+ */
+ store : false,
+
+ /**
+ * @cfg {String|Roo.Element} el The container element.
+ */
+ el : '',
+
+ /**
+ * @cfg {String|Roo.Template} tpl The template used by this View
+ */
+ tpl : false,
+ /**
+ * @cfg {String} dataName the named area of the template to use as the data area
+ * Works with domtemplates roo-name="name"
+ */
+ dataName: false,
+ /**
+ * @cfg {String} selectedClass The css class to add to selected nodes
+ */
+ selectedClass : "x-view-selected",
+ /**
+ * @cfg {String} emptyText The empty text to show when nothing is loaded.
+ */
+ emptyText : "",
+
+ /**
+ * @cfg {String} text to display on mask (default Loading)
+ */
+ mask : false,
+ /**
+ * @cfg {Boolean} multiSelect Allow multiple selection
+ */
+ multiSelect : false,
+ /**
+ * @cfg {Boolean} singleSelect Allow single selection
+ */
+ singleSelect: false,
+
+ /**
+ * @cfg {Boolean} toggleSelect - selecting
+ */
+ toggleSelect : false,
+
+ /**
+ * @cfg {Boolean} tickable - selecting
+ */
+ tickable : false,
+
+ /**
+ * Returns the element this view is bound to.
+ * @return {Roo.Element}
+ */
+ getEl : function(){
+ return this.wrapEl;
+ },
+
+
+
+ /**
+ * Refreshes the view. - called by datachanged on the store. - do not call directly.
+ */
+ refresh : function(){
+ //Roo.log('refresh');
+ var t = this.tpl;