/////////////////////////////////////////////////////////////////////////// // Copyright © 2014 - 2018 Esri. All Rights Reserved. // // Licensed under the Apache License Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. /////////////////////////////////////////////////////////////////////////// define([ 'dojo/_base/lang', 'dojo/Evented', 'dojo/_base/html', 'dojo/_base/declare', 'dijit/_WidgetBase', 'dojo/on', 'dojo/query', 'dijit/_TemplatedMixin', 'dijit/_WidgetsInTemplateMixin', 'dojo/text!./AdvancedListValueSelect.html', 'jimu/utils' ],function(lang, Evented, html, declare, _WidgetBase, on, query, _TemplatedMixin, _WidgetsInTemplateMixin, template, jimuUtils) { return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin, Evented], { templateString: template, selectType: null, dataList:[], checkedList:[], //save value checkedLabelList: [], //save label or alias _itemLabelW: 215, //ellipsis if label's width is larger than this ifFristPage: true, // if it is the first page to show queryState: true,// if it is quering data from server isCacheFinish: false, keyQueryMode: false, cacheQueryMode : false, emptyStr: '', postMixInProperties:function(){ this.inherited(arguments); this.jimuCommonNls = window.jimuNls.common; this.Nls = window.jimuNls.filterBuilder; this.noDataNls = window.apiNls.widgets.FeatureTable.noData; }, postCreate: function(){ this.inherited(arguments); // this.checkedList = []; if(this.selectType === 'unique'){ this.inputType = 'radio'; }else{ this.inputType = 'checkbox'; } if(this.controlType === 'multipleDynamic' || this.controlType === 'uniqueDynamic'){ html.addClass(this.listContainer, "items-setting-dropdown-content"); this.searchKeyInput.style.display = 'block'; } if(this.controlType === 'uniqueDynamic'){ html.addClass(this.listContainer, 'items_content_no_selected_toggle'); } if(this.runtime){ // this.listContainer.style.height = 230 + 'px'; html.addClass(this.listContainer, "items-widget-content"); if(this.selectUI !== 'dropdown'){ //predefind & expanded html.addClass(this.listContainer, "items-widget-expaned-content"); html.addClass(this.listContent, "jimu-multiple-items-expanded-list"); } }else{ html.addClass(this.listContainer, "items-setting-popup-content"); this.searchKeyInput.style.display = 'block'; // this.initDoms(); } //for enable listSelect for every item when type is predefined if(!this.runtime && this.controlType === 'predefined'){ html.addClass(this.listContainer, "items-setting-dropdown-content"); html.addClass(this.listContainer, 'items_content_no_selected_toggle'); this.searchKeyInput.style.display = 'block'; } this._addCBXClickEvent(); if(this.selectUI === 'dropdown' || (this.controlType === 'predefined' && !this.runtime)){ this._addCBXHoverEvent(); } //show custom label string when runtime & predefined this.disPlayLabel = 'value'; if(this.runtime && (this.controlType === 'multiplePredefined' || this.controlType === 'uniquePredefined')){ this.disPlayLabel = 'alias'; } //for selected model if(this.controlType === 'multipleDynamic'){ this.selectedToggleDiv.style.display = 'block'; this.selectedToggle = query('.showAllIcon', this.selectedToggleDiv)[0]; this.own(on(this.selectedToggleDiv, 'click', lang.hitch(this, '_toggleFilter'))); this._addSelectedContainerEvent(); } }, _toggleFilter: function(evt){ var target = evt.target; if(html.hasClass(target, 'clearAllSelectedIcon')){ //clear selected all this._clearAllSelected(); return; } if(html.hasClass(target, 'iconHover') || html.hasClass(target, 'selectedToggleDiv')){ return; } if(html.hasClass(target, 'showAllIcon')){ this.selectedContainer.style.display = 'none'; }else{ this._initSelectedContainerItems(); this.selectedContainer.style.display = 'block'; } html.removeClass(this.selectedToggle, 'iconHover'); this.selectedToggle = target; html.addClass(this.selectedToggle, 'iconHover'); evt.stopPropagation(); }, showAllList: function(){ var applied = html.hasClass(this.selectedToggle, 'showSelectedIcon') && html.hasClass(this.selectedToggle, 'iconHover'); if(applied){ html.removeClass(this.selectedToggle, 'iconHover'); this.selectedToggle = query('.showAllIcon', this.selectedToggleDiv)[0]; html.addClass(this.selectedToggle, 'iconHover'); html.setStyle(this.selectedContainer, 'display', 'none'); } }, _clearAllSelected: function(){ var listContainer; if(html.hasClass(this.selectedToggle, 'showAllIcon')){ listContainer = this.listContainer; }else{ listContainer = this.selectedListContent; } var inputs = query('.item .checkInput.checked', listContainer); for(var key = 0; key < inputs.length; key ++){ // html.removeClass(inputs[key], 'checked'); inputs[key].click(); } }, _initSelectedContainerItems: function(){ this.selectedListContent.innerHTML = ''; var items = ''; var labelRuntimeClass = this.runtime ? ' labelRuntime' : ''; for(var index = 0; index < this.checkedList.length; index ++){ var value = this.checkedList[index]; var label = this.disPlayLabel === 'value' ? value : this.checkedLabelList[index]; var dataAttr = this.isNumberField ? "data=" + value : "data='" + value + "'"; var item = '
' + '
' + '
' + label + '
' + '
'; items += item; } this.selectedListContent.innerHTML = items; }, _addSelectedContainerEvent: function(){ this.own(on(this.selectedListContent, 'click', lang.hitch(this, function(evt){ var evtTarget = evt.target; var cbxTarget, labelTarget; if(html.hasClass(evtTarget,'item')){ cbxTarget = evtTarget.firstElementChild; labelTarget = evtTarget.firstElementChild.nextSibling; }else if(html.hasClass(evtTarget,'checkInput')){ cbxTarget = evtTarget; labelTarget = evtTarget.nextSibling; }else if(html.hasClass(evtTarget,'label')){ cbxTarget = evtTarget.previousSibling; labelTarget = evtTarget; }else{ evt.stopPropagation(); return; } //show var target = cbxTarget, name = this._getNodeText(labelTarget); var value = name; if(this.disPlayLabel === 'alias' || this.disPlayLabel === 'label'){ value = decodeURIComponent(html.getAttr(target, 'data')); } if(html.hasClass(target, 'checked')){ if(this.inputType === 'radio'){ return; } html.removeClass(target, 'checked'); //update list this._updateCheckedList('remove', value, name); this.checkCBXItems(); this.emit("advancedListValueSelect_itemUnChecked", name); }else{ if(this.inputType === 'radio' && this.currentItem){ if(this.currentItem === true){ this.currentItem = this.getCurrentItem(); } html.removeClass(this.currentItem, 'checked'); } html.addClass(target, 'checked'); this._updateCheckedList('add', value, name); this.checkCBXItems(); this.emit("advancedListValueSelect_itemChecked", name); } evt.stopPropagation(); }))); }, _getNodeText: function(target){ // return target.textContent || target.innerText || target.innerHTML; return target.textContent || target.innerText || ''; }, _updateCheckedList: function(type,name,label){ if(name !== this.emptyStr){ name = this.isNumberField ? parseFloat(name): name; } if(type === 'remove'){ for(var key in this.checkedList){ if(this.checkedList[key] === name || (this.isNumberField && isNaN(this.checkedList[key]) && isNaN(name))){//isNaN('abc') = true this.checkedList.splice(key,1);//remove this unChecked name this.checkedLabelList.splice(key,1); break; //only remove first value, when there're same values in the checkedList. } } }else{ if(this.inputType === 'radio'){ this.checkedList = [name]; this.checkedLabelList = [label]; }else{ //allow same values, it could be [1,2,2,3] when multiplePredefined // if(this.checkedList.indexOf(name) < 0){ this.checkedList.push(name); this.checkedLabelList.push(label); // } } } }, _updateCheckedLabelList: function(valueLabels){ this.checkedLabelList = []; for(var key = 0; key < this.checkedList.length; key ++){ for(var index = 0; index < valueLabels.length; index ++){ if(this.checkedList[key] === valueLabels[index].value){ this.checkedLabelList.push(valueLabels[index].label); } } } }, _updateCheckedLabelListFromCheckedList: function(){ for(var key = 0; key < this.checkedList.length; key ++ ){ this.checkedLabelList.push(this.checkedList[key] + ''); } }, _createTarget: function(evt){ var text = this._getNodeText(evt.target); var name = text.split(': ')[1]; this.emit("advancedListValueSelect_itemChecked", name); }, //delete item by namename _deleteCBXItem: function(){//name }, _getCheckInputItems: function(){ return query('.item .checkInput', this.listContent); }, //get all checked values getListCheckedValuesOrigin: function(){ var checkedVals = []; var items = this._getCheckInputItems(); //can't get this.listContent in this function for(var key = 0; key < items.length; key ++){ var item = items[key]; var value = this._getNodeText(item.nextSibling); if(html.hasClass(item,'checked')){ checkedVals.push(value); } } return checkedVals; }, getListCheckedValues: function(){ var checkedVals = []; var strs = lang.clone(this.checkedList); for(var key = 0; key < strs.length; key ++){ var str = strs[key]; var value = this.isNumberField ? parseFloat(str):str; checkedVals.push(value); } return checkedVals; }, //get all values with checked field getListValues: function(){ var valsObj = []; // var checkedVals = []; var items = this._getCheckInputItems(); if(items.length === 0){return this.dataList;} for(var key = 0; key < items.length; key ++){ var item = items[key]; var value = this._getNodeText(item.nextSibling); if(this.disPlayLabel === 'alias' || this.disPlayLabel === 'label'){ value = decodeURIComponent(html.getAttr(item, 'data')); } value = this.isNumberField ? parseFloat(value): value; var valObj = {value: value, isChecked: false}; if(html.hasClass(item,'checked')){ valObj.isChecked = true; // checkedVals.push(value); } valsObj.push(valObj); } // return checkedVals; return valsObj; }, //get if value exist getIfValueExist: function(name){ var items = this._getCheckInputItems(); for(var key = 0; key < items.length; key ++){ var item = items[key]; var value = this._getNodeText(item.nextSibling); if(name === value){ return true; } } return false; }, //get all checked values getCurrentItem: function(){ // var items = query('.item .radio', this.listContent); var items = this._getCheckInputItems(); for(var key = 0; key < items.length; key ++){ var item = items[key]; if(html.hasClass(item,'checked')){ return item; } } return null; }, //set cbx item checked status depending on predefined table checkCBXItems: function(ifClearValue){ var value = ifClearValue ? '' : this.valueInput.get('value'); this.valueInput.set('value',value); var items = query('.item .label', this.listContent); for(var key = 0; key < items.length; key ++){ var item = items[key]; var valStr = this.disPlayLabel === 'value' ? this._getNodeText(item) : decodeURIComponent(html.getAttr(item.previousSibling, 'data')); // var itemVal = this.isNumberField ? parseFloat(item.innerText) : item.innerText; var itemVal = this.isNumberField ? parseFloat(valStr) : valStr; if(this.checkedList.indexOf(itemVal) >= 0 || (this.isNumberField && this.checkedList.indexOf(parseFloat(itemVal)) >= 0)){//for number string data html.addClass(item.previousSibling, 'checked'); }else{ html.removeClass(item.previousSibling, 'checked'); } } }, reset: function(){ this.listContent.innerHTML = ''; }, //add data to list when get data every time, don't need to clear previous data. //isCheck: if need checked option's status //isInit: if need to init select content setCBXData: function(valueLabels, isCheck, ifInit, isResetPopup){ if(!isResetPopup){ this.queryState = false; } valueLabels = valueLabels? valueLabels : []; // for listSelect Popup on predefined setting page // close popup (destroy popup) while it's quering data from server. if(!this.listContent){ return; } html.setStyle(this.noDataTips, 'display', 'none'); var realCheckedNum = 0; var labelBig = this.inputType === 'radio' ? ' labelBig' : ''; var labelRuntimeClass = this.runtime ? ' labelRuntime' : ''; var innerHTML = this.listContent.innerHTML; if(ifInit){ this.listContent.innerHTML = ''; innerHTML = ''; if((this.controlType === 'uniquePredefined' && this.enableEmpty) || (this.controlType === 'uniqueDynamic' && !this.keyQueryMode)){//cacheQueryMode var _checkedClass = '', itemActiveClass = ''; if(this.checkedList[0] === this.emptyStr){ _checkedClass = ' checked'; itemActiveClass = ' active'; realCheckedNum = 1; } if(this.checkedList.length === 0){//uniquePredefined _checkedClass = ' checked'; this.currentItem = true; realCheckedNum = 1; } var _dataAttr = "data='" + this.emptyStr + "'"; innerHTML = '
' + '
' + '
' + this.emptyStr + '
'; } this.listContainer.scrollTop = 0;//reset scroll position } if(valueLabels.length === 0){ var _contentHtml = this.listContent.innerHTML.replace(/(^\s*)|(\s*$)/g, ""); if(_contentHtml === '' && (!this.cacheQueryMode || this.isCacheFinish)){ html.setStyle(this.noDataTips, 'display', 'block'); } if(_contentHtml === ''){ this.listContent.innerHTML = innerHTML; } return this.listContent; } var items = ''; for(var index = 0; index < valueLabels.length; index ++){ var valueLabel = valueLabels[index]; var checkedClass = ''; if(isCheck){ if(this.runtime && (this.controlType === 'multiplePredefined' || this.controlType === 'uniquePredefined')){ if(valueLabel.isChecked){ checkedClass = ' checked'; this.currentItem = true; realCheckedNum ++; } }else if(this.checkedList.indexOf(valueLabel.value) >= 0 || (this.isNumberField && this.checkedList.indexOf(parseFloat(valueLabel.value)) >= 0)){//for number string data checkedClass = ' checked'; this.currentItem = true; realCheckedNum ++; } } // var selectClass = "radio"; // var dataAttr = this.isNumberField ? "data=" + valueLabel.value : "data='" + valueLabel.value + "'"; var dataValue = this.isNumberField ? valueLabel.value : encodeURIComponent(valueLabel.value);//string maybe has ',"" var dataAttr = "data=\"" + dataValue + "\""; var item = '
' + // '
' + '
' + '
' + // valueLabel.value + '
' + valueLabel[this.disPlayLabel] + '
' + ''; items += item; } var checkedDiff = this.checkedList.length - realCheckedNum; if(this.runtime && checkedDiff > 0){ for(var key = 0;key < checkedDiff; key ++){ this.emit("advancedListValueSelect_itemUnChecked", ''); } } this.listContent.innerHTML = innerHTML + items; // var containerH = html.getStyle(this.listContainer, 'height') + 15; // html.setStyle(this.listContainer, 'height', containerH + 'px'); return this.listContent; }, //set content with data which query by searchkey(this data doesn't require paging) setCBXContentBySearch: function(valueLabels, isResetPopup){//, pageSize // var name = this.searchName; // pageSize = pageSize ? pageSize : this.pageSize; if(valueLabels.length === 0){ this.setCBXData([], false, true, isResetPopup);//, pageSize // if(this.controlType !== 'multipleDynamic'){ // this._addCreateDom(name); // } }else{ this.setCBXData(valueLabels, true, true, isResetPopup);//, pageSize // if(this.controlType !== 'multipleDynamic'){ // var ifExist = this.getIfValueExist(name); // if(!ifExist){ // this._addCreateDom(name); // }else{ // html.setStyle(this.createNewItem, 'display', 'none'); // } // } } }, //query from local cache _onSearchKeyChange: function(){ var name = this.valueInput.get('value'); this.searchName = name; this.listContainer.scrollTop = 0;//reset scroll position this.reset(); this.ifFristPage = true; this.keyQueryMode = true; this.cacheQueryMode = true; this.emit("advancedListValueSelect_searchKeyLocal", name); if(this.codedValues){ return; } if(!this.isCacheFinish){ html.setStyle(this.loadMoreDataBtn, 'display', 'block'); } //back to query from server mode if(name.length === 0){ this.keyQueryMode = false; this.cacheQueryMode = false; this.queryState = false; html.setStyle(this.loadMoreDataBtn, 'display', 'none'); } }, _loadMoreDataFromServer: function(){ this.ifFristPage = true; this.keyQueryMode = true; this.cacheQueryMode = false; this.queryState = true; html.setStyle(this.loadMoreDataBtn, 'display', 'none'); //only show once time after local querying var name = this.valueInput.get('value'); this.searchName = name; this.listContainer.scrollTop = 0;//reset scroll position // if(name.length !== 0){ //search // this.keyQueryMode = true; // runtime & predefined need 'search' and 'addBtn' // setting & multiple need 'search' no 'addBtn' if(this.controlType === 'multipleDynamic' || this.controlType === 'uniqueDynamic'){//multiple this.emit("advancedListValueSelect_searchKey", name); }else if(this.runtime){ // console.log('runtime'); }else{//setting---two predefineds this.emit("advancedListValueSelect_searchKey", name); } // }else{ // this.keyQueryMode = false; // // this.createNewItem.style.display = 'none'; // this.reset(); // // this.setCBXData([], false, true, 1); // this.emit("advancedListValueSelect_addNextPage"); // // this.listContentStore.placeAt(this.listContent); // } }, // _addCreateDom: function(name){ // this.createNewItem.style.display = 'block'; // var label = this.Nls.createValue; // var str = label.replace('${value}', name); // this.createNewItem.innerText = str; // }, currentHoverItem: null, _addCBXHoverEvent: function(){ this.own(on(this.listContent, 'mouseover', lang.hitch(this, function(event){ var target = event.target || event.srcElement; var itemDom; if(html.hasClass(target, 'item')){ itemDom = target; }else{ itemDom = jimuUtils.getAncestorDom(target, function(dom){ return html.hasClass(dom, 'item'); }, 3); } if(this.currentHoverItem){ html.removeClass(this.currentHoverItem, 'active'); } html.addClass(itemDom, 'active'); this.currentHoverItem = itemDom; }))); this.own(on(this.listContent, 'mouseout', lang.hitch(this, function(){ if(this.currentHoverItem){ html.removeClass(this.currentHoverItem, 'active'); } this.currentHoverItem = null; }))); }, _addCBXClickEvent: function(){ // this.own(on(this.valueInput, 'blur', lang.hitch(this, function(){ // this._loadMoreDataFromServer(); // }))); this.own(on(this.valueInput, 'change', lang.hitch(this, function(){ this._onSearchKeyChange(); }))); this.own(on(this.loadMoreDataBtn, 'click', lang.hitch(this, function(){ this._loadMoreDataFromServer(); }))); // if(this.controlType === 'multipleDynamic' || this.controlType === 'uniqueDynamic'){ this.own(on(this.listContainer, 'scroll', lang.hitch(this, this.dropDownScroll))); // } this.own(on(this.searchKeyInput, 'click', lang.hitch(this, function(evt){ evt.stopPropagation(); }))); // var contentDoms = query('.jimu-multiple-items-list', this.cbxPopup.domNode)[0]; this.own(on(this.listContainer, 'click', lang.hitch(this, function(evt){ var evtTarget = evt.target; var cbxTarget, labelTarget; if(html.hasClass(evtTarget,'item')){ cbxTarget = evtTarget.firstElementChild; labelTarget = evtTarget.firstElementChild.nextSibling; }else if(html.hasClass(evtTarget,'checkInput')){ cbxTarget = evtTarget; labelTarget = evtTarget.nextSibling; }else if(html.hasClass(evtTarget,'label')){ cbxTarget = evtTarget.previousSibling; labelTarget = evtTarget; }else{ evt.stopPropagation(); return; } this._setCBXChecked(cbxTarget, this._getNodeText(labelTarget)); evt.stopPropagation(); }))); }, scrollDiff:100,//add more data when the distance is 100px from bottom dropDownScroll: function(evt){ if(this.runtime && (this.controlType === "uniquePredefined" || this.controlType === "multiplePredefined")){ return; } if(this.cacheQueryMode || this.codedValues){ return; } if(this.queryState){ this.listContainer.scrollTop = this.containerScrollTop; // html.setStyle(this.listContainerOverlay, 'display', 'block'); return; }else{ // html.setStyle(this.listContainerOverlay, 'display', 'none'); } var target = evt.target; var diff = target.scrollHeight - target.clientHeight; if(diff - target.scrollTop <= this.scrollDiff){ if(!this.queryState){ this.containerScrollTop = this.listContainer.scrollTop; this.queryState = true; this.ifFristPage = false; this.emit("advancedListValueSelect_addNextPage"); } } }, _setCBXChecked: function(target, name){ var value = name; if(this.disPlayLabel === 'alias' || this.disPlayLabel === 'label'){ value = decodeURIComponent(html.getAttr(target, 'data')); } if(html.hasClass(target, 'checked')){ if(this.inputType === 'radio'){ //close list when reChecked radio item if(!this.runtime && this.controlType === 'predefined'){ this.emit("advancedListValueSelect_itemCheckedForPredefined", value, name); }else{ this.emit("advancedListValueSelect_itemChecked", name); } return; } html.removeClass(target, 'checked'); this._updateCheckedList('remove', value, name); this.emit("advancedListValueSelect_itemUnChecked", name); }else{ if(this.inputType === 'radio' && this.currentItem){ if(this.currentItem === true){ this.currentItem = this.getCurrentItem(); } if(this.currentItem){ html.removeClass(this.currentItem, 'checked'); } } html.addClass(target, 'checked'); this.currentItem = target; // if(!this.runtime){ this._updateCheckedList('add', value, name); if(!this.runtime && this.controlType === 'predefined'){ this.emit("advancedListValueSelect_itemCheckedForPredefined", value, name); }else{ this.emit("advancedListValueSelect_itemChecked", name); } // } } }, initDoms: function(valueLabels,ifCheck){ this.setCBXData(valueLabels,ifCheck); }, getData: function(){ }, refreshData: function(){ this.checkCBXItems(); }, validate: function() { var displayVal = this.checkedList.length ? '12345678': null; if(this.checkedList.length === 1 && this.checkedList[0] === this.emptyStr){ displayVal = null; } //return null if there are some invalid datas(number type) in checkList if(this.isNumberField){ for(var key = 0; key < this.checkedList.length; key ++){ var itemVal = this.checkedList[key]; if(itemVal === this.emptyStr){ continue; } if(isNaN(itemVal)){ displayVal = null; break; } } } this.set("DisplayedValue", displayVal); return true; // var valid = false; // var valList = this.getListValues(); // if(this.controlType === "uniqueDynamic"){ // if(valList || valList === 0){ // valid = true; // } // }else{ // if(valList && valList.length > 0){ // valid = true; // } // } // if(valid){ // this.set("DisplayedValue", '100000000'); // } // return true; }, setRequired: function(required){ this.mutiValuesSelect.set("required", required); }, destroy:function(){ // if(this.valueInputBlur){ // this.valueInputBlur.remove(); // } html.destroy(this.domNode); // this = null; this.inherited(arguments); } }); });