var EXPO = EXPO || {}; //isolated namespace // module requires JQuery library, dna.js template engine (http://dnajs.org/) // protection against duplication of a module code if (EXPO.searchBlock){ console.warn('WARNING: EXPO.searchBlock is already defined!'); }else{ EXPO.searchBlock = (function() { // variables var that = {}; //default module setting that.settings = { place:{ id:'pw-place', selectedItemTemplate:'csb-selected', ajaxUrl:'http://hit.expomap.ru/search-form/' }, subject:{ id:'pw-subj', ajaxUrl:'http://hit.expomap.ru/search-form/' } }; that.lang ={}; //dependence's // module require dna.js tiny templating engine var common = EXPO.common; //private // statci class methods var Json2URI = function (jsonObj) { var str = Object.keys(jsonObj).map(function(key){ return encodeURIComponent(key) + '=' + encodeURIComponent(jsonObj[key]); }).join('&'); return ('?'+str); }, //STATIC MEtHOD for make ajax GET request and launch handler if exist or return data getRequest = function (dataToSend,url,handler) { if(!dataToSend){ dataToSend = ''; } $.ajax({ type: 'GET', url: url, data:dataToSend, success: function(data) { if(typeof handler == 'function'){ handler(data); } else{ return data; } } }); }, renameProperty = function (obj,oldName, newName) { // Check for the old property name to avoid a ReferenceError in strict mode. if (obj.hasOwnProperty(oldName)) { obj[newName] = obj[oldName]; } return this; }, // analogue of Array.length but for object getObjectLength = function (obj) { var size = 0, key; for (key in obj) { if (obj.hasOwnProperty(key)) size++; } return size; }, // returns string that contains selected values in both modal windows. values separated by ',' // string is cutted to N symbols length getSelectedToString = function(container, cutLength){ var $container = $('#'+container), index = 0, stringToReturn = '', closingSymbol = '...', closerText = EXPO.searchBlock.settings.closerText, closerTextSingle = EXPO.searchBlock.settings.closerTextSingle, dividerSymbol = ''; $element = $container.find('.csbs-text'); if($element.length > 2){ if($element.eq(0).text().length < cutLength){ dividerSymbol = ','; stringToReturn += $element.eq(0).text() + dividerSymbol + $element.eq(1).text() + closerText.replace('_',$element.length-2); }else{ stringToReturn += $element.eq(0).text() + closerText.replace('_',$element.length-1); } } else if($element.length == 2){ if($element.eq(0).text().length < cutLength){ dividerSymbol = ','; stringToReturn += $element.eq(0).text() + dividerSymbol + $element.eq(1).text() + closerTextSingle.replace('_',$element.length-2); }else{ stringToReturn += $element.eq(0).text() + closerTextSingle.replace('_',$element.length-1); } }else if($element.length){ stringToReturn += $element.eq(0).text(); }else{ stringToReturn = false; } return stringToReturn; //if($element.length > 1){ // dividerSymbol = ', '; //} //if($element.length){ // $element.each(function () { // if (index == ($element.length -1)){ // stringToReturn += $(this).text(); // }else{ // stringToReturn += $(this).text()+dividerSymbol; // // } // index++ // }); // stringToReturn = stringToReturn .substring(0, cutLength); // stringToReturn += closingSymbol; // return stringToReturn; //} else{ // return false; //} }, //ajax pending process indicator $waiter = $('.wait-ajax.absolute'), //temporal stub for testing autocomplete field/ must remove this before production stubForAutocomplete = [{"url": null, "text": "\u041d\u0430\u043f\u0438\u0442\u043a\u0438", "id": 142, "label": "\u0422\u0435\u0433\u0438:"}, {"url": null, "text": "\u0421\u043f\u0438\u0440\u0442\u043d\u044b\u0435 \u043d\u0430\u043f\u0438\u0442\u043a\u0438", "id": 277, "label": "\u0422\u0435\u0433\u0438:"}, {"url": null, "text": "\u0410\u043b\u043a\u043e\u0433\u043e\u043b\u044c\u043d\u044b\u0435 \u043d\u0430\u043f\u0438\u0442\u043a\u0438", "id": 2463, "label": "\u0422\u0435\u0433\u0438:"}, {"url": null, "text": "\u041f\u0440\u043e\u0434\u0443\u043a\u0442\u044b \u043f\u0438\u0442\u0430\u043d\u0438\u044f \u0438 \u043d\u0430\u043f\u0438\u0442\u043a\u0438", "id": 4393, "label": "\u0422\u0435\u0433\u0438:"}, {"url": "/expo/event-autochtona-2014", "text": "Autochtona 2014", "id": 2802, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-coteca-2014", "text": "COTECA 2014", "id": 2479, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-food-ing-international-2014", "text": "Food-Ing International 2014", "id": 2548, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-envies-culinaries-2014", "text": "Envies Culinaries 2014", "id": 2554, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-forum-vini-2014", "text": "Forum Vini 2014", "id": 2694, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-bionord-2014", "text": "BioNord 2014", "id": 2718, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-biosud-2014", "text": "BioSud 2014", "id": 2719, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-brau-beviale-2014", "text": "Brau Beviale 2014", "id": 2517, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-florida-restaurant-lodging-show-2014", "text": "Florida Restaurant & Lodging Show 2014", "id": 2546, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-expo-comida-latina-los-angeles-2014", "text": "Expo Comida Latina Los Angeles 2014", "id": 2563, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-china-bevtek-2014", "text": "China BevTek 2014", "id": 2592, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-gaste-2015", "text": "GASTE 2015", "id": 2619, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-gastro-2014", "text": "GastRo 2014", "id": 2732, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-bbc-goodfood-show-scotland-2014", "text": "BBC GoodFood Show Scotland 2014", "id": 2558, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-china-brew-china-beverage-cbb-2014", "text": "China Brew & China Beverage (CBB) 2014", "id": 2600, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-fhc-china-2014", "text": "FHC China 2014", "id": 2689, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-coffee-fest-portland-2014", "text": "Coffee Fest Portland 2014", "id": 2477, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-coffee-fest-st-louis-2014", "text": "Coffee Fest St. Louis 2014", "id": 2478, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-bbc-good-food-show-birmingham-fall-2014", "text": "BBC Good Food Show Birmingham Fall 2014", "id": 2555, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}, {"url": "/expo/event-bbc-good-food-show-birmingham-summer-2014", "text": "BBC Good Food Show Birmingham Summer 2014", "id": 2556, "label": "\u0412\u044b\u0441\u0442\u0430\u0432\u043a\u0438:"}]; $(function () { //$('.modal-approve').on('click', function () { // $.fancybox.close(); //}); /* modal windows opening */ var fbPopupOptions = { padding: 0, fitToView: false }; }); // Constructor for modal window 'select subject' var SubjectModal = function(options){ // options init this.opt = options; var self = this, index = 0, $subjWrap = $('#'+self.opt.subjectTriggerWrapId), $topicBox, modalId = self.opt.id, $modal = $('#'+modalId), $checkBox = $('.csb-menu-input', $modal), $selectedItemsWrap = $('.csb-selected-items',$modal), setDefault = self.opt.defaultOn, applyBtnClass = self.opt.applyBtnClass, $modalTrigger = $('#'+self.opt.modalTrigger), afterRenderHandler = function () { $waiter.hide(); }, triggerSetText = function () { var selectedString, cutLength = 16; selectedString = getSelectedToString(self.opt.selectedItemsContainer,cutLength); if(selectedString && selectedString != '~~text~~' && selectedString != '~~text~~...'){ $modalTrigger.text(selectedString); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).addClass('active'); }else{ $modalTrigger.text($modalTrigger.data('default')); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).removeClass('active'); } }; //this modal window DOM Instance this.$modalInst = $('#'+modalId); //clones of tags for selected(checked) subject (powered by dna.js objects: see http://dnajs.org/) this.itemsSelected = {}; // clones of sublist of selected(checked) subject (powered by dna.js objects: see http://dnajs.org/) this.sublist= {}; // Jquery object of filtering input (autocomplete input) this.$inputFilter = $('#'+self.opt.filterInputId); this.$selectedItemsWrap = $selectedItemsWrap; $(function () { $('.topicChecks', $subjWrap).on('change', function () { if($(this).prop('checked')){ self._setVisible($(this).val()); }else{ self._setUnvisible($(this).val()); } }); // selected topic by default self.opt.defaultOn[] for(index = 0; index < setDefault.length; index++){ $topicBox = $('#'+setDefault[index]) $topicBox.prop('checked',true); $topicBox.trigger('change'); } $modal.on('click', 'a.trigger', function () { var name = $(this).attr('data-name'), id = $(this).attr('data-id'), tmplId = $(this).attr('data-template-id'), $sublist = $(this).siblings('.dna-container'); // no more than once execution if($(this).attr('data-sub') == 'true'){ if($(this).parent().hasClass('level1')){ if(!$sublist.children().length){ $waiter.show(); self._renderSublist({name:name,id:id}, tmplId, afterRenderHandler); $(this).parent().addClass('active'); }else{ //slideUp & Down stuff self._slideToggle($sublist, $(this).parent()); } } } return false; }); $checkBox.on('change', function (event, param) { var checkboxId = $(this).attr('id'), $label = $(this).closest('.custom-radio-check'), $parent = $(this).closest('.level'), $parentCheckBox = $parent.parent().closest('.level').children('.custom-radio-check').find('.csb-menu-input'), $sublist = $parent.children('.sublist'); if(!param){ if($label.hasClass('active')){ $label.removeClass('active'); }else{ $label.addClass('active'); } if(this.checked){ var text = $(this).closest('.level').find('.trigger').first().text(), tplObj = {'text':text,'id':checkboxId}; //tags field logic if(!$selectedItemsWrap.hasClass('visible')){ $selectedItemsWrap.addClass('visible'); } self._addTag(checkboxId, tplObj); // proper selection and selection group logic if($sublist.length){ //$('.csb-menu-input',$sublist).prop('checked',true); $('.csb-menu-input',$sublist).each(function () { var thisId = this.getAttribute('id'), tagText = $(this).closest('.level').find('.trigger').first().text(), tagObj = {'text':tagText,'id':thisId}, DOMCheckboxWrap = this.parentNode, DOMlabel = common.closest(this,'custom-radio-check'); this.checked = true; self._destroyTag(thisId); //$label.addClass('active'); common.addClass(DOMlabel,'active'); //$(this).trigger('change',['true']); //self._addTag(thisId,tagObj); }); }else{ $parent = $parent.parent().closest('.level') // if checked items count equals all items count then parent item is checked and tags for children - deleted if ( $('.csb-menu-input',$parent.find('.sublist')).length == $('.csb-menu-input:checked',$parent.find('.sublist')).length){ var parentId = $parentCheckBox[0].getAttribute('id'), parentText = $parentCheckBox.closest('.level').find('.trigger').first().text(), DOMlabel =common.closest(this,'custom-radio-check'), DOMParentLabel = common.closest(DOMlabel.parentNode.parentNode,'level'), parentObj = {'text':parentText,'id':parentId}; $('.csb-menu-input:checked',$parent.find('.sublist')).each(function () { //var DOMlabel =common.closest(this,'custom-radio-check'); //this.checked = false; //$(this).trigger('change',['true']); //common.removeClass(DOMlabel,'active'); self._destroyTag(this.getAttribute('id')); }); $parentCheckBox.prop('checked', true); common.addClass($(DOMParentLabel).find('.custom-radio-check')[0],'active'); //$parentCheckBox.trigger('change',['true']); self._addTag(parentId,parentObj); } } //!uncheck event }else { self._destroyTag(checkboxId); if(!$selectedItemsWrap.children('.dna-clone').length){ $selectedItemsWrap.removeClass('visible'); } //uncheck all sublist items while parent item is unchecked if($sublist.length){ //destroy all tags for sublist items $('.csb-menu-input',$sublist).each(function () { var thisId = $(this).attr('id'), DOMlabel = common.closest(this,'custom-radio-check'); this.checked = false; common.removeClass(DOMlabel, 'active'); //$(this).trigger('change',['true']); self._destroyTag(thisId); }); }else{ // parent item is unchecked and tags for every children item are made if($parentCheckBox.length && $parentCheckBox[0].checked){ var DOMlabel = common.closest($parentCheckBox[0],'custom-radio-check'), DOMParentItem = common.closest(DOMlabel,'level'), DOMSublist = DOMParentItem.querySelector('.sublist'); $parentCheckBox.prop('checked', false); common.removeClass(DOMlabel, 'active'); //$parentCheckBox.trigger('change',['true']); self._destroyTag($parentCheckBox.attr('id')); // checks children items $('.csb-menu-input:checked',DOMSublist).each(function () { var id = this.getAttribute('id'), tagText = common.closest(this, 'level').querySelector('.trigger').textContent, //tagText = $(this).closest('.level').find('.trigger').first().text(), tagObj = {'text':tagText,'id':id}; self._addTag(id,tagObj); }); } } } triggerSetText(); } }); $('.csbs-del', $selectedItemsWrap).on('click', function () { var checkboxId = $(this).attr('data-checkbox-id'), $uncheckBoxes = $('#'+checkboxId); $uncheckBoxes.prop('checked', false); $uncheckBoxes.trigger('change'); dna.destroy(self.itemsSelected[checkboxId]); if(!$selectedItemsWrap.children('.dna-clone').length){ $selectedItemsWrap.removeClass('visible'); } return false; }); $('.clear', $modal).on('click', function () { self.resetList(); return false; }); self._autocompleteInit(); $('.'+applyBtnClass, $modal).on('click', function () { self.applyHandler(this); return false; }); // кнопка "очистить параметры" $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).on('click', function () { self.resetList(); }); }); }; SubjectModal.prototype = { //get ajax response when want sublists _getAjax: function (dataToSend, handler) { var self = this; if(!dataToSend){ dataToSend = ''; } $waiter.css({display:'block'}); $.ajax({ type: 'GET', url: self.opt.ajaxUrl, data:dataToSend, success: function(data) { if(typeof handler == 'function'){ $waiter.hide(); handler(data); } else{ return data; } } }); }, // _setVisible and _setUnvisible filter list accordingly to checked checkbox in 'select type' part of modal _setVisible:function(type){ var self = this; $('.'+type, self.$modalInst).addClass('visible'); }, _setUnvisible: function (type) { var self = this, $li = $('.'+type, self.$modalInst); $li.find('input[type="checkbox"]').each(function () { var $this = $(this); if($this.prop('checked')){ $this.prop('checked', false); $this.trigger('change'); } }); $li.find('.dna-container').each(function () { if($(this).children().length){ $(this).addClass('hidden'); } }); $li.removeClass('visible'); }, //check particular checkbox input _checkCheckBox: function (id,name) { var self = this, $chckBox; if(name == 'th'){ $chckBox = $('#tid_'+id, self.$modalInst); }else if(name == 'tg'){ $chckBox = $('#tgid_'+id, self.$modalInst); } if($chckBox.length && !$chckBox.prop('checked')){ $chckBox.prop('checked',true); $chckBox.trigger('change'); } }, check: function (id,name) { var self = this, $chckBox; if(name == 'th'){ $chckBox = $('#tid_'+id, self.$modalInst); }else if(name == 'tg'){ $chckBox = $('#tgid_'+id, self.$modalInst); } if($chckBox.length){ $chckBox.prop('checked',true); $chckBox.trigger('change'); $chckBox.parent().addClass('active'); } }, //initiliazing and setup autocomplete field for subject list _autocompleteInit : function () { var self = this, dataObj, text , form = self.$inputFilter.attr('data-form'),index, $completeWrap = $('#'+self.opt.autoCompleteId), firstComplete = true, selectTag = function (event, ui) { //check of repeating execution $waiter.show(); var firstTime = true; for (var prop in self.sublist) { for (var prop2 in self.sublist[prop]) { if (prop2 == ui.item.value){ firstTime = false; } } } if($('#tid_'+ui.item.value+'[name="'+ui.item.name+'"]:checked').length){ firstTime = false; } // ban of repeating execution if (firstTime) { // konec var $checkbox = $('#tid_' + ui.item.value+'[name="'+ui.item.name+'"]'), requestObj, requestName, treeLoadHandler = function (data) { // make checkboxes selected after loading if(getObjectLength(data)){ self._loadParentTree(data, function () { self._checkCheckBox(ui.item.value,'tg'); $waiter.hide(); }); }else{ $waiter.hide(); console.warn() } }; // load tree related to selected item if (!$checkbox.length) { requestObj = { id: ui.item.value, name: ui.item.name }; getRequest(requestObj, self.opt.getParentUrl, treeLoadHandler); } else{ $waiter.hide(); $checkbox.prop('checked', true); $checkbox.trigger('change'); } } }, requestHandler = function(data){ dataObj = data; for(index = 0; index < dataObj.length; ++index) { renameProperty(dataObj[index],'text','label'); } for(index = 0; index < dataObj.length; ++index) { renameProperty(dataObj[index],'id','value'); } if(!self.$inputFilter.hasClass('ui-autocomplete-input')){ self.$inputFilter.autocomplete({ source:dataObj, minLength: 0, appendTo:$completeWrap, select:function(event, ui){ self.$inputFilter.val(''); self.$inputFilter.trigger('keyup'); selectTag(event, ui); event.preventDefault(); // return ui.label; } }); self.$inputFilter.autocomplete('search',""); firstComplete = false; }else{ self.$inputFilter.autocomplete('search',""); } }; // var newData = ['banan','banan2','banan3','banan4','banan5']; self.$inputFilter.attr('autocomplete', 'on'); self.$inputFilter.on('keyup', function (event) { text = $(this).val(); event.stopImmediatePropagation(); if (text.length > 2 && firstComplete){ getRequest({'term':text, 'form':form}, self.opt.autoCompleteUrl, requestHandler); firstComplete = false; }else if(text.length == 0 && !firstComplete){ if(self.$inputFilter.hasClass('ui-autocomplete-input')){ self.$inputFilter.autocomplete( "destroy" ); firstComplete = true; } } return false; }).click(function () { return false; }); }, //render first level sublist _renderSublist: function (dataObj, tmplId, handler) { var self = this, index = 0, template = tmplId + '-sub', ajaxHandler = function (data) { if(data.length){ self.sublist[template] = {}; // for dna.clone definition see dnajs.org for (index ; index < data.length; index++) { self.sublist[template][data[index].id] = dna.clone(tmplId, data[index]); } handler(data.length); }else{ $waiter.hide(); } }; self._getAjax(dataObj, ajaxHandler); }, _loadParentTree: function (data, handler, counter) { var self = this, dataObj = data, optObj, sublistTemplateId, nestedObj,nestedSublistTemplateId, // makes request in order to recieve children list information fires after request for parent list handlerNested = function (length) { var $checkbox = $('#tid_'+dataObj.id), afterAll = function () { $waiter.hide(); counter||counter===0?handler(counter):handler(); }; $waiter.hide(); if($checkbox.length && getObjectLength(self.curDNA[sublistTemplateId+'-sub']) == length){ nestedObj = { name:dataObj.name, id:dataObj.id }; $waiter.show(); nestedSublistTemplateId = $('#id_'+dataObj.id).closest('.level').children('.trigger').attr('data-template-id'); self._renderNested(nestedObj, afterAll, nestedSublistTemplateId, dataObj.id); } }, handlerParent = function (){ $waiter.hide(); counter||counter===0?handler(counter):handler(); }; $waiter.show(); optObj = { name:dataObj.name, id:dataObj.id }; sublistTemplateId = $('#tid_'+dataObj.id).closest('.level').children('.trigger').attr('data-template-id'); self._renderSublist(optObj,sublistTemplateId,handlerParent); }, // for dna.clone definition see dnajs.org _destroyTag:function(checkboxId){ var self = this; if(self.itemsSelected[checkboxId]){ dna.destroy(self.itemsSelected[checkboxId]); } }, // for dna.clone definition see dnajs.org _addTag: function (checkboxId, tplObj) { var self = this; self.itemsSelected[checkboxId] = dna.clone(self.opt.selectedItemTemplate,tplObj); }, //hide or show sublists according active selected link _slideToggle:function ($sublist, $this){ if($sublist.hasClass('hidden')){ $sublist.removeClass('hidden'); $this.addClass('active'); }else{ $sublist.addClass('hidden').find('ul').addClass('hidden'); $this.removeClass('active'); } }, resetList: function () { var self = this; for (var key in self.itemsSelected) { if (self.itemsSelected.hasOwnProperty(key)) { $('#'+key, self.$selfContainer).prop('checked', false).trigger('change'); dna.destroy(self.itemsSelected[key]); } } self.$selectedItemsWrap.removeClass('visible'); }, // кнопка применить applyHandler: function (it) { $.fancybox.close(); } }; // Constructor for popup window 'select place' // select places window var PlacesModal = function(options){ // object properties //modal Window options this.opt = options; var self = this, $modal = $('#'+self.opt.id), $checkBox = $('input[type="checkbox"]', $modal), $selectedItemsWrap = $('.csb-selected-items',$modal), DOMTagsWrapper = $('.csb-selected-items',$modal)[0], $modalTrigger = $('#'+self.opt.modalTrigger), applyBtnClass = self.opt.applyBtnClass, idPrefix = 'id_', triggerSetText = function () { var selectedString, cutLength = 16; selectedString = getSelectedToString(self.opt.selectedItemsContainer,cutLength); if(selectedString && selectedString != '~~text~~' && selectedString != '~~text~~...'){ $modalTrigger.text(selectedString); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).addClass('active'); }else{ $modalTrigger.text($modalTrigger.data('default')); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).removeClass('active'); } }; // current template instances this.curDNA = {}; // place modal list items that had selected this.itemsSelected = {}; this.selectedWrap = $selectedItemsWrap; this.$selfContainer = $modal; this.$modal = $modal; this.idPrefix = idPrefix; //флаг для управления очередью асинхронных запросов this.isReceived = true; // Jquery object of filtering input (autocomplete input) this.$inputFilter = $('#'+self.opt.filterInputId); $(function () { self._autocompleteInit(); $modal.on('click', 'a.trigger', function () { var name = $(this).attr('data-name'), id = $(this).attr('data-id'), that = this, tmplId = $(this).attr('data-template-id'), $sublist = $(this).siblings('.dna-container'), afterRenderHandler = function (elem, data) { var DOMParent = common.closest(that,'level'), DOMParentCheckbox = DOMParent.querySelector('.csb-menu-input'); $('.csb-menu-input', $sublist).each(function () { var DOMCheckboxWrap = common.closest(this,'custom-radio-check'); if(!this.selected){ if(DOMParentCheckbox.checked){ this.checked = true; common.addClass(DOMCheckboxWrap,'active'); } } }); $waiter.hide(); }; // no more than once execution if($(this).attr('data-sub') == 'true'){ if($(this).parent().hasClass('level1')){ if(!$sublist.children().length){ $waiter.show(); self._renderSublist({name:name,id:id}, tmplId, afterRenderHandler); }else{ //slideUp & Down stuff self._slideToggle($sublist, $(this).parent()); } }else if($(this).parent().hasClass('level2')){ if(!$sublist.children().length){ self._renderNested({name:name,id:id}, afterRenderHandler, tmplId, id); $(this).parent().addClass('active'); } else{ //slideUp & Down stuff self._slideToggle($sublist, $(this).parent()); } } } return false; }); $checkBox.on('change', function (event, param) { var id = this.getAttribute('id'), fakeCheckboxClass = 'custom-radio-check', fakeCheckbox = common.closest(this, fakeCheckboxClass), itemClass = 'level', activeClass = 'active', sublistClass = 'sublist', checkboxClass = 'csb-menu-input', highestItemClass = 'level1', tagClass = 'csb-selected', tagButtonClass = 'csbs-del', triggerClass = 'trigger', tagIdAttribute = 'data-checkbox-id', DOMParentRow = common.closest(this, itemClass), DOMParentItem = common.hasClass(DOMParentRow, highestItemClass) == false?common.closest(DOMParentRow.parentNode, itemClass):DOMParentRow, DOMParentCheckbox = DOMParentItem.querySelector('.'+checkboxClass), DOMSublist = DOMParentItem.querySelector('.'+sublistClass), DOMSublistInner = DOMParentRow.querySelector('.'+sublistClass), DOMHighestItem = common.closest(this, highestItemClass), DOMHighestCheckbox = DOMHighestItem.querySelector('.'+checkboxClass), selectSublist = function (it) { var DOMParentItem = common.closest(it, itemClass) || this, DOMSublist = DOMParentItem.querySelector('.'+sublistClass); $('.'+checkboxClass, DOMSublist).each(function () { selectItem(this); }); }, unSelectSublist = function (it) { var DOMParentItem = common.closest(it, itemClass) || this, DOMSublist = DOMParentItem.querySelector('.'+sublistClass); $('.'+checkboxClass, DOMSublist).each(function () { unSelectItem(this); }); }, selectParent = function (it) { var DOMParentRow = common.closest(it, itemClass), DOMParentItem; if(common.hasClass(DOMParentRow,'level1')){ DOMParentItem = DOMParentRow; }else{ DOMParentItem = common.closest(DOMParentRow.parentNode, itemClass); } common.addClass(DOMParentItem.querySelector('.'+fakeCheckboxClass), activeClass); DOMParentItem.querySelector('.'+checkboxClass).checked = true; //it.selected = true; }, unSelectParent = function (it) { var DOMParentRow = common.closest(it, itemClass), DOMParentItem = common.closest(DOMParentRow.parentNode, itemClass) || DOMParentRow; common.removeClass(DOMParentItem.querySelector('.'+fakeCheckboxClass), activeClass); DOMParentItem.querySelector('.'+checkboxClass).checked = false; //it.checked = false; }, selectItem = function (it) { var itFakeCheckbox = common.closest(it, fakeCheckboxClass); common.addClass(itFakeCheckbox, activeClass); it.checked = true; }, unSelectItem = function (it) { var itFakeCheckbox = common.closest(it, fakeCheckboxClass); common.removeClass(itFakeCheckbox, activeClass); it.checked = false; }, allChildrenSelected = function () { //var DOMselected = DOMSublist.querySelectorAll('.'+checkboxClass+':checked'), var DOMSublistParent = common.closest(DOMSublist,sublistClass), $selected = $(DOMSublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked'), selectedCount = $selected.length, //allCount = DOMSublist.querySelectorAll('.'+checkboxClass).length; allCount = $(DOMSublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass).length; if(allCount == selectedCount && selectedCount != 0){ return true; } else{ return false; } }, parentSelected = function () { var parentCheckbox = DOMParentItem.querySelector('.'+checkboxClass); if(parentCheckbox.checked){ return true; }else{ return false; } }, // Функционал добавления тегов: если есть в панели выбранный элемент либо его дочерние то удалить эти эдементы и разместить выбранный; иначе разместить выбранные. refreshTags = function (it) { var DOMSublist = common.closest(it,sublistClass); var DOMItem = common.closest(it,itemClass); var DOMSublistInner = DOMItem.querySelector('.'+sublistClass); var DOMAllTags = DOMTagsWrapper.querySelectorAll('.'+tagClass); var ARRsublist; var ARRsublistChildren = DOMSublist.querySelector('.'+sublistClass)?$('.'+checkboxClass+':checked',DOMSublist.querySelector('.'+sublistClass)):null; var ARRsublistChildrenLength = ARRsublistChildren?ARRsublistChildren.length:null; var ARRSublistIds = []; var ARRAllTagsIds = []; var allTagsLength = 0; var sublistIdsLength = 0; var itId = it.getAttribute('id'); var i = 0, j= 0, t= 0, tmp, k = 0; var tagId; var tagText = DOMParentRow.querySelector('.'+triggerClass).innerHTML; // если есть дочерние элементы if(DOMSublistInner){ ARRsublist = $(DOMSublistInner).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked') //получаем массив id жлементовЮ для которых есть тег for(k; k < ARRsublist.length; k++){ tmp = ARRsublist[k].getAttribute('id'); ARRSublistIds.push(tmp); } //очистк for(t; t 2 && firstComplete){ getRequest({'term':text, 'form':form}, self.opt.autoCompleteUrl, requestHandler); firstComplete = false; }else if(text.length == 0 && !firstComplete){ if(self.$inputFilter.hasClass('ui-autocomplete-input')){ self.$inputFilter.autocomplete( "destroy" ); firstComplete = true; } } return false; }).click(function () { return false; }); }, // loads and shows list tree related to selected id // data - is JSON object with information about parent elements. // handler is callback function _loadParentTree: function (data, handler, counter) { var self = this, dataObj = data, optObj, sublistTemplateId, nestedObj,nestedSublistTemplateId, $midleLevelCheckbox = $('#id_'+dataObj.id), // makes request in order to recieve children list information fires after request for parent list handlerNested = function (length) { var $checkbox = $('#id_'+dataObj.id), afterAll = function () { $waiter.hide(); counter||counter===0?handler(counter):handler(); }; $waiter.hide(); if($checkbox.length && getObjectLength(self.curDNA[sublistTemplateId+'-sub']) == length){ nestedObj = { name:dataObj.name, id:dataObj.id }; $waiter.show(); nestedSublistTemplateId = $('#id_'+dataObj.id).closest('.level').children('.trigger').attr('data-template-id'); self._renderNested(nestedObj, afterAll, nestedSublistTemplateId, dataObj.id); } }, handlerParent = function (){ $waiter.hide(); counter||counter===0?handler(counter):handler(); }; $waiter.show(); //if element has parent element if(dataObj.hasOwnProperty('parent')){ //if checbox is existed if($midleLevelCheckbox.length){ nestedObj = { name:dataObj.name, id:dataObj.id }; nestedSublistTemplateId = $midleLevelCheckbox.closest('.level').children('.trigger').attr('data-template-id'); self._renderNested(nestedObj, function(){$waiter.hide();handler();}, nestedSublistTemplateId, dataObj.id); }else{ optObj = { name:dataObj.parent.name, id:dataObj.parent.id }; sublistTemplateId = $('#id_'+dataObj.parent.id).closest('.level').children('.trigger').attr('data-template-id'); self._renderSublist(optObj,sublistTemplateId,handlerNested); } }else{ optObj = { name:dataObj.name, id:dataObj.id }; sublistTemplateId = $('#id_'+dataObj.id).closest('.level').children('.trigger').attr('data-template-id'); self._renderSublist(optObj,sublistTemplateId,handlerParent); } }, applyHandler: function (it) { $.fancybox.close(); }, // проверка выделен ли указанный чекбокс isSelected: function (id) { var self = this; return $(self.idPrefix+id, self.$modal).prop('checked'); } }; //Constructor for perios selector modal window var PeriodModal = function (options) { this.opt = options; var self = this, $dateFrom = $('#'+self.opt.dateFrom), $dateTo = $('#'+self.opt.dateTo), $modal = $('#'+self.opt.id), $modalTrigger = $('#'+self.opt.modalTrigger), applyBtnClass = self.opt.applyBtnClass, inputsTostring = function(){ var self = this, stringToReturn = '', toChar = $modalTrigger.data('lng-to'), fromChar = $modalTrigger.data('lng-from'), toVal = $.trim($dateTo.val()), fromVal = $.trim($dateFrom.val()); if(toVal != ''&& fromVal != ''){ stringToReturn = fromChar+': '+fromVal+' '+toChar+': '+toVal+'.'; } else if (toVal != ''&& fromVal == ''){ stringToReturn = toChar+': '+toVal+'.'; } else if (toVal == ''&& fromVal != ''){ stringToReturn = fromChar+': '+fromVal+'.'; } return stringToReturn; }, triggerSetText = function (selectedString) { var cutLength = 24; if(selectedString != ''){ $modalTrigger.text(selectedString).siblings('.trigger-label').addClass('hidden'); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).addClass('active'); }else{ $modalTrigger.text($modalTrigger.data('default')).siblings('.trigger-label').removeClass('hidden'); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).removeClass('active'); } }, // проверяет и исправляет значение полей окна дата и ипсравляет значения так, чтобы в поле от всегда была дата "до"(меньше) даты в поле "по" checkInterval = function (it) { var itId = it.getAttribute('id'), itVal = it.value, itValInt = Date.parse(itVal), thatId, thatVal, thatValInt, bfr; if(itId == self.opt.dateFrom){ thatId = $dateTo[0].getAttribute('id'); thatVal = $dateTo[0].value; }else { thatId = $dateFrom[0].getAttribute('id'); thatVal = $dateFrom[0].value; } thatValInt = Date.parse(thatVal); if(thatValInt > itValInt && thatValInt != 0 && thatValInt){ bfr = document.getElementById(itId).value; document.getElementById(itId).value = document.getElementById(thatId).value; document.getElementById(thatId).value = bfr; }else if(thatValInt < itValInt && thatValInt != 0 && thatValInt){ bfr = document.getElementById(thatId).value; document.getElementById(thatId).value = document.getElementById(itId).value; document.getElementById(itId).value = bfr; } }; this.$dateFrom = $dateFrom; this.$dateTo = $dateTo; this.$modalTrigger = $modalTrigger; $(function () { $.datepicker.setDefaults($.datepicker.regional["ru"]); $dateFrom.datepicker({ dateFormat: 'dd.mm.yy', showOn: 'button', showOtherMonths: true, constrainInput: true, onClose: function( selectedDate ) { $dateTo.datepicker( "option", "minDate", selectedDate ); } }).inputmask("99.99.9999",{ showMaskOnHover:false, 'oncomplete': function () { checkInterval(this); } }); $dateTo.datepicker({ dateFormat: 'dd.mm.yy', showOn: 'button', showOtherMonths: true, constrainInput: true, onClose: function( selectedDate ) { $dateFrom.datepicker( "option", "maxDate", selectedDate ); } }).inputmask("99.99.9999",{ showMaskOnHover:false, 'oncomplete': function () { checkInterval(this); } }); $('input[type="text"]',$modal).on('change', function () { var stringToset = inputsTostring(); triggerSetText(stringToset); }); $('.'+applyBtnClass, $modal).on('click', function () { self.applyHandler(this); return false; }); $modalTrigger.siblings('.'+self.opt.clearAllButtonClass).on('click', function () { $(this).removeClass('active'); self.resetList(); }); }); }; PeriodModal.prototype = { inputsTostring:function(){ var self = this, stringToReturn = '', toChar = self.$modalTrigger.data('lng-to'), fromChar = self.$modalTrigger.data('lng-from'), toVal = $.trim(self.$dateTo.val()), fromVal = $.trim(self.$dateFrom.val()); if(toVal != ''&& fromVal != ''){ stringToReturn = fromChar+': '+fromVal+' '+toChar+': '+toVal+'.'; } else if (toVal != ''&& fromVal == ''){ stringToReturn = toChar+': '+toVal+'.'; } else if (toVal == ''&& fromVal != ''){ stringToReturn = fromChar+': '+fromVal+'.'; } return stringToreturn; }, //todo: доделать resetList: function () { this.$dateFrom.val(''); this.$dateTo.val(''); this.$modalTrigger.text(this.$modalTrigger.attr('data-default')); }, // функционал кнопки применить applyHandler: function (it) { $.fancybox.close(); } }; //constructor for main searchfield var MainField = function (options) { this.opt = options; this.opt.anyChar = false; var self = this, firstComplete = true; this.$field = $('#'+self.opt.id); // option when is true autocomplite fires each time user enters value this.$completeWrap = $('#'+self.opt.autoCompleteWrapId); //much faster than JQuery this.DOMcompleteWrap = document.getElementById(self.opt.autoCompleteWrapId); //data recieved by ajax response this.afterClear; this.rawData = { items:[], set:function (data) { this.items = data; this._rawDataChange(); }, get: function () { return this.items; }, //executes when this.rawData changes _rawDataChange: function (e) { var self = this, index; for(index = 0; index < self.items.length; index++) { renameProperty(self.items[index],'text','label') renameProperty(self.items[index],'id','value') } } }; this.completeName = 'autocomplete', this.firstComplete = true; //autocomplete event handler // this.rawData.addEventListener('rawDataChange',self._rawDataChange,false); // switch off default autocomplete behaviour //autocomplete="on | off" this.$field.attr('autocomplete','off'); self.$field.on('keyup', function (event) { var reqObj; text = $(this).val(); event.stopImmediatePropagation(); if(self.dataForm){ reqObj = { 'term':text, 'form':self.dataForm } }else{ reqObj = { 'term':text } } if(self.opt.anyChar){ if (text.length > 2){ getRequest(reqObj, self.opt.autoCompleteUrl, function (data) { if(self.$field.hasClass('ui-autocomplete-input')){ self.$field[self.completeName]( "destroy" ); } self.rawData.set(data); self._initAutoComplete(); self.showList(''); }); } else if(text.length === 0){ if(self.$field.hasClass('ui-autocomplete-input')){ self.$field[self.completeName]( "destroy" ); common.removeClass(self.DOMcompleteWrap,'full-visible'); self._resetmodals(self.afterClear); } } }else{ if (text.length > 2 && firstComplete){ getRequest(reqObj, self.opt.autoCompleteUrl, function (data) { self.rawData.set(data); self._initAutoComplete(); self.showList(''); // self.DOMcompleteWrap.addClass('full-visible'); }); firstComplete = false; }else if(text.length == 0 && !firstComplete){ if(self.$field.hasClass('ui-autocomplete-input')){ self.$field[self.completeName]( "destroy" ); common.removeClass(self.DOMcompleteWrap,'full-visible'); self._resetmodals(self.afterClear); firstComplete = true; } }else{ if(self.$field.hasClass('ui-autocomplete-input')){ self.showList(text); } } } //for autocomplete on each keypress //for normal flow autocomplete return false; }).click(function () { return false; }); }; MainField.prototype = { //Jquery autocomplete initialization and // autocomplete functionality on this.$field _initAutoComplete: function () { var self = this; self.$field[self.completeName]({ source:self.rawData.get(), minLength: 0, appendTo:self.DOMcompleteWrap, select:function(event, ui){ self._afterSelect(event, ui); }, close: function () { common.removeClass(self.DOMcompleteWrap,'full-visible'); }, open: function () { common.addClass(self.DOMcompleteWrap,'full-visible'); } }); }, // functionality of selected object in autocomplete list _afterSelect: function (event, ui) { var self = this; event.preventDefault(); // much faster than jquery if(ui.item.url){ window.location = ui.item.url; } else if(ui.item.label.length){ self.$field[0].value = ui.item.label; self.selectCheckBoxes(ui.item.id, ui.item.name); } }, // method fires callback when field is cleared _resetmodals: function (callback) { if(callback){ callback(); }else{ return 0; } }, // public property for redefine _afterSelect selectHandler: function () { }, //public object modificator. newRender: function (handler) { var self = this; handler(this); self.$field.data(); }, //select checkboxes if therer is coincidence with search result and modal subject modal window selectCheckBoxes: function (id, name) { }, //simple shows out autocomplete list showList: function (text) { self = this; this.$field[self.completeName]('search',text); }, //brings data from server and transfer it to handler function pullData: function (handler) { } }; //прототип модального окна общего для всех Modal = function (options) { var self = this; this.id; this.opt = options; this.DOMwrap = document.getElementById(options.id); this.DOM = this.DOMwrap.querySelector('.'+ options.wrapClass); $('.modal-close',this.DOM).on('click', function () { self.close(); }); $('.modals > *').on('click', function (ev) { if($(ev.target.parentNode).find(self.DOMwrap).length){ self.close(); } }); }; Modal.prototype = { pullData: function (selector) { this.id = selector.substr(1); $(selector).show().siblings().hide(); this.refresh(); }, open: function () { $(this.DOMwrap).fadeIn(); common.addClass(document.body, 'ov-hidden'); }, close: function () { $(this.DOMwrap).fadeOut(); common.removeClass(document.body, 'ov-hidden'); }, refresh: function () { var self = this; self.DOM.style.width = self.opt.size[self.id].width +'px'; self.DOM.style.minHeight = self.opt.size[self.id].height +'px'; self.DOM.style.marginLeft = -(self.opt.size[self.id].width/2)+'px'; self.DOM.style.marginTop = -(self.opt.size[self.id].height/2)+'px'; } } // methods //initialization of the general properties and it events handlers functionality that.init = function(options) { // settings extending $.extend(this.lang, options.lang); options.lang = null; $.extend(this.settings, options); // begin of initialization var self = this, submitHandler = function () { $(self.DOMform).find('input[name="~~name~~"]').remove(); }; if(this.settings.searchData != 'None' && this.settings.searchData){ this.previousSearch = JSON.parse(this.settings.searchData) } this.DOMform = document.getElementById(this.settings.formId); $(this.DOMform).on('submit', function () { submitHandler(); }); // custom autocomplete realization for exibition input $.widget( "custom.exibitionComplete", $.ui.autocomplete,{ _renderMenu: function( ul, items ) { var that = this, currentCategory = ""; $.each( items, function( index, item ) { if ( item.cat != currentCategory && item.cat) { ul.append( "
  • " + item.cat + "
  • " ); currentCategory = item.cat; }/*else if(item.url){ ul.append( "
  • " + item.label + "
  • " ); }*/ that._renderItemData( ul, item ); }); } }); this.exhibitionField = new MainField(self.settings.firstField); this.exhibitionField.completeName = 'exibitionComplete'; this.exhibitionField.opt.anyChar = true; //modal windows this.placesModal = new PlacesModal(self.settings.place); this.subjModal = new SubjectModal(self.settings.subject); this.periodModal = new PeriodModal(self.settings.period); this.exhibitionField.selectCheckBoxes = function (id, name) { var self = this, DOMCheckboxes, nestedObj, iName = name; if(name == 'th'){ DOMCheckboxes = document.getElementById(self.opt.prefix+id); }else if(name == 'tg'){ DOMCheckboxes = document.getElementById(self.opt.prefixInner+id); iName = 'th'; } $waiter.show(); // load tree related to selected item if (!DOMCheckboxes) { nestedObj = { name:name, id:id }; // requestObj = { // id: ui.item.value, // name: ui.item.name // }; getRequest(nestedObj, EXPO.searchBlock.subjModal.opt.getParentUrl, function (data) { EXPO.searchBlock.subjModal._loadParentTree(data, function(){ EXPO.searchBlock.subjModal._checkCheckBox(id, name); }); }); } else{ $waiter.hide(); $(DOMCheckboxes).prop('checked', true); $(DOMCheckboxes).trigger('change'); } }; /////**** this.placesField = new MainField(self.settings.placeField); this.placesField.dataForm = EXPO.searchBlock.placesModal.$inputFilter.attr('data-form'); this.placesField.selectCheckBoxes = function(id,name){ var self = this, DOMCheckboxes, nestedObj; DOMCheckboxes = document.getElementById(self.opt.prefix+id); if (!DOMCheckboxes) { nestedObj = { name:name, id:id }; getRequest(nestedObj, EXPO.searchBlock.placesModal.opt.getParentUrl, function (data) { EXPO.searchBlock.placesModal._loadParentTree(data, function(){ EXPO.searchBlock.placesModal._checkCheckBox(id, name); }); }); } else{ $waiter.hide(); $(DOMCheckboxes).prop('checked', true); $(DOMCheckboxes).trigger('change'); } }; // uncheck all checboxes in modal and clear label beneath searchfield this.exhibitionField.afterClear = function () { self.subjModal.resetList(); }; this.placesField.afterClear = function () { self.placesModal.resetList(); }; //модальное окно this.modalWindow = new Modal(self.settings.modal); this.periodModal.applyHandler = function () { self.modalWindow.close(); $(self.DOMform).submit(); }; this.placesModal.applyHandler = function () { //$.fancybox.close(); self.modalWindow.close(); $(self.DOMform).submit(); //self.DOMform.submit(); }; this.subjModal.applyHandler = function () { //$.fancybox.close(); self.modalWindow.close(); $(self.DOMform).submit(); //self.DOMform.submit(); }; // // modal window calling $('.'+self.settings.modalTriggerClass).on('click', function () { self.modalWindow.pullData(this.getAttribute('href')); self.modalWindow.open(); return false; }); // заполнение полей предыдущими значениями $(function () { if(self.previousSearch){ for (var i = 0; i < self.previousSearch.inputs.length; i++) { // окно выбора тематики if (self.previousSearch.inputs[i].name == 'th'){ self.subjModal._loadParentTree(self.previousSearch.inputs[i], function (innerI) { if(self.previousSearch.inputs[innerI].children){ self.subjModal.check(self.previousSearch.inputs[innerI].children.id, self.previousSearch.inputs[innerI].children.name); }else{ self.subjModal.check(self.previousSearch.inputs[innerI].id, self.previousSearch.inputs[innerI].name); } }, i); // окно выбора мест } else if (self.previousSearch.inputs[i].name == 'area'){ //todo для renderSublist надо передавать только родителя и прародителя if(self.previousSearch.inputs[i].children && self.previousSearch.inputs[i].children.children){ self.placesModal.selectTag(self.previousSearch.inputs[i].children.children); }else if (self.previousSearch.inputs[i].children){ self.placesModal.selectTag(self.previousSearch.inputs[i].children); } else if(self.previousSearch.inputs[i]){ self.placesModal.selectTag(self.previousSearch.inputs[i]); } } } } }); }; return that; }()); }