You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1859 lines
56 KiB
1859 lines
56 KiB
var EXPO = EXPO || {}; //isolated namespace
|
|
EXPO.events = EXPO.events || {};
|
|
if (EXPO.events.feed) {
|
|
console.warn('WARNING: EXPO.eventsFeed is already defined!');
|
|
} else {
|
|
EXPO.events.feed = (function () {
|
|
// variables
|
|
var that = {};
|
|
|
|
//default module setting
|
|
that.opt = {};
|
|
//dependence's
|
|
var com = EXPO.common;
|
|
//private
|
|
var Filter = function (opt) {
|
|
this.opt = opt;
|
|
this.DOMbody = document.getElementById(opt.bodyId);
|
|
|
|
},
|
|
/**
|
|
* make ajax GET request and launch handler if exist or return data
|
|
* @param {Object|string} dataToSend
|
|
* @param {string} url
|
|
* @param {function} handler - function to execute when task is ready
|
|
*/
|
|
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;
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* rename name of property of an object/ Check for the old property name to avoid a ReferenceError in strict mode.
|
|
* @param {Object} obj object to rename its properties
|
|
* @param {string} oldName
|
|
* @param {string} newName
|
|
* @returns {renameProperty}
|
|
*/
|
|
renameProperty = function (obj,oldName, newName) {
|
|
if (obj.hasOwnProperty(oldName)) {
|
|
obj[newName] = obj[oldName];
|
|
|
|
}
|
|
return this;
|
|
},
|
|
/**
|
|
* analogue of Array.length but for object instance
|
|
* @param {Object} obj - Object to count its method
|
|
* @returns {number}
|
|
*/
|
|
getObjectLength = function (obj) {
|
|
var size = 0, key;
|
|
for (key in obj) {
|
|
if (obj.hasOwnProperty(key)) size++;
|
|
}
|
|
return size;
|
|
},
|
|
$waiter = $('.wait-ajax.absolute'),
|
|
Json2URI = function (jsonObj) {
|
|
var str = Object.keys(jsonObj).map(function(key){
|
|
return encodeURIComponent(key) + '=' + encodeURIComponent(jsonObj[key]);
|
|
}).join('&');
|
|
return ('?'+str);
|
|
};
|
|
|
|
// methods
|
|
Filter.prototype = {
|
|
show: function () {
|
|
//$(this.DOMbody).show();
|
|
$(this.DOMbody).slideDown();
|
|
},
|
|
hide: function () {
|
|
$(this.DOMbody).hide();
|
|
//$(this.DOMbody).slideUp();
|
|
|
|
}
|
|
};
|
|
|
|
// places and subject modals
|
|
/**
|
|
* Constructor for modal window 'select subject'
|
|
* @param {Object} options
|
|
* @constructor
|
|
*/
|
|
var SubjectModal = function (options) {
|
|
/**
|
|
* options init
|
|
* @type {Object}
|
|
*/
|
|
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 = $('#'+this.opt.selectedItemsContainer, $modal),
|
|
setDefault = self.opt.defaultOn,
|
|
applyBtnClass = self.opt.applyBtnClass,
|
|
$modalTrigger = $('#' + self.opt.modalTrigger),
|
|
DOMfilterBox = document.getElementById(self.opt.bodyId),
|
|
/**
|
|
* executed after render of modal Window
|
|
* @function
|
|
*/
|
|
afterRenderHandler = function () {
|
|
$waiter.hide();
|
|
|
|
},
|
|
$waiter = $('.wait-ajax.absolute');
|
|
|
|
/**
|
|
* this modal window DOM Instance
|
|
* @type {*|jQuery|HTMLElement}
|
|
*/
|
|
this.$modalInst = $('#' + modalId);
|
|
|
|
/**
|
|
* clones of tags for selected(checked) subject (powered by dna.js objects: see http://dnajs.org/)
|
|
* in modal window
|
|
* @type {Object}
|
|
*/
|
|
this.itemsSelected = {};
|
|
/**
|
|
* clones of tags for selected(checked) subject (powered by dna.js objects: see http://dnajs.org/)
|
|
* on the page itself
|
|
* @type {Object}
|
|
*/
|
|
this.tagsBoxItems = {};
|
|
/**
|
|
* clones of sublist of selected(checked) subject (powered by dna.js objects: see http://dnajs.org/)
|
|
* @type {Object}
|
|
*/
|
|
this.sublist = {};
|
|
/**
|
|
* Jquery object of filtering input (autocomplete input)
|
|
* @type {*|jQuery|HTMLElement}
|
|
*/
|
|
this.$inputFilter = $('#' + self.opt.filterInputId);
|
|
/**
|
|
* label span element that contain short description for active filter
|
|
* @type {*|jQuery|HTMLElement}
|
|
*/
|
|
this.$label = $(document.getElementById(this.opt.labelId));
|
|
|
|
this.$selectedItemsWrap = $selectedItemsWrap;
|
|
/**
|
|
* flag for management of turn of asynchronous requests
|
|
* @type {boolean}
|
|
*/
|
|
this.isReceived = true;
|
|
|
|
$(function () {
|
|
// topic checkbox selected event
|
|
$('.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 list and sublist behavior
|
|
$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;
|
|
});
|
|
// modal theme checkbox change behavior
|
|
$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).each(function () {
|
|
var thisId = this.getAttribute('id'),
|
|
tagText = $(this).closest('.level').find('.trigger').first().text(),
|
|
DOMlabel = com.closest(this, 'custom-radio-check');
|
|
|
|
this.checked = true;
|
|
self._destroyTag(thisId);
|
|
com.addClass(DOMlabel, 'active');
|
|
});
|
|
|
|
} 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 = com.closest(this, 'custom-radio-check'),
|
|
DOMParentLabel = com.closest(DOMlabel.parentNode.parentNode, 'level'),
|
|
parentObj = {'text': parentText, 'id': parentId};
|
|
$('.csb-menu-input:checked', $parent.find('.sublist')).each(function () {
|
|
|
|
self._destroyTag(this.getAttribute('id'));
|
|
});
|
|
$parentCheckBox.prop('checked', true);
|
|
com.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 = com.closest(this, 'custom-radio-check');
|
|
this.checked = false;
|
|
|
|
com.removeClass(DOMlabel, 'active');
|
|
self._destroyTag(thisId);
|
|
});
|
|
$sublist.addClass('hidden');
|
|
$parent.removeClass('active');
|
|
} else {
|
|
// parent item is unchecked and tags for every children item are made
|
|
if ($parentCheckBox.length && $parentCheckBox[0].checked) {
|
|
var DOMlabel = com.closest($parentCheckBox[0], 'custom-radio-check'),
|
|
DOMParentItem = com.closest(DOMlabel, 'level'),
|
|
DOMSublist = DOMParentItem.querySelector('.sublist');
|
|
$parentCheckBox.prop('checked', false);
|
|
com.removeClass(DOMlabel, 'active');
|
|
self._destroyTag($parentCheckBox.attr('id'));
|
|
// checks children items
|
|
|
|
$('.csb-menu-input:checked', DOMSublist).each(function () {
|
|
var id = this.getAttribute('id'),
|
|
tagText = com.closest(this, 'level').querySelector('.trigger').textContent,
|
|
tagObj = {'text': tagText, 'id': id};
|
|
self._addTag(id, tagObj);
|
|
});
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
});
|
|
//delete tag behavior
|
|
$('.' + self.opt.deleteTagClass, $modal).on('click', function (e) {
|
|
e.stopPropagation();
|
|
var checkboxId = $(this).attr('data-checkbox-id'),
|
|
$uncheckBoxes = $('#' + checkboxId);
|
|
$uncheckBoxes.prop('checked', false);
|
|
$uncheckBoxes.trigger('change');
|
|
self._refreshLabel();
|
|
if (!$selectedItemsWrap.children('.dna-clone').length) {
|
|
$selectedItemsWrap.removeClass('visible');
|
|
}
|
|
return false;
|
|
});
|
|
$('.del-on-page').on('click',function () {
|
|
var dataCheckboxId = $(this).attr('data-checkbox-id');
|
|
$('.' + self.opt.deleteTagClass+'[data-checkbox-id="'+dataCheckboxId+'"]', $modal).trigger('click');
|
|
});
|
|
self._autocompleteInit();
|
|
$('.' + applyBtnClass, $modal).on('click', function () {
|
|
self.applyHandler(this);
|
|
return false;
|
|
});
|
|
// кнопка "очистить параметры"
|
|
|
|
$('.'+self.opt.clearAllButtonClass,$modal).on('click', function (e) {
|
|
e.preventDefault();
|
|
self.resetList();
|
|
return false;
|
|
});
|
|
});
|
|
};
|
|
/**
|
|
* methods
|
|
* @type {{_getAjax: Function, _setVisible: Function, _setUnvisible: Function, _checkCheckBox: Function, check: Function, _autocompleteInit: Function, _renderSublist: Function, _loadParentTree: Function, _destroyTag: Function, _addTag: Function, _slideToggle: Function, resetList: Function, applyHandler: Function}}
|
|
*/
|
|
SubjectModal.prototype = {
|
|
/**
|
|
* get ajax response when want sublists
|
|
* @param {Object|sting} dataToSend
|
|
* @param {function} handler - fires after request is complete
|
|
* @private
|
|
*/
|
|
_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;
|
|
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* filter list accordingly to checked checkbox in 'select type' part of modal
|
|
* @param {string} type
|
|
* @private
|
|
*/
|
|
_setVisible: function (type) {
|
|
var self = this;
|
|
$('.' + type, self.$modalInst).addClass('visible');
|
|
},
|
|
/**
|
|
* filter list accordingly to checked checkbox in 'select type' part of modal
|
|
* @param {string} type
|
|
* @private
|
|
*/
|
|
_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
|
|
* @param {string} id
|
|
* @param {string} name
|
|
* @private
|
|
*/
|
|
_checkCheckBox: function (id, name) {
|
|
var self = this,
|
|
$chckBox;
|
|
if (name == 'th') {
|
|
$chckBox = $('#tid_' + self.opt.prefix + id, self.$modalInst);
|
|
} else if (name == 'tg') {
|
|
$chckBox = $('#tgid_' + self.opt.prefix + id, self.$modalInst);
|
|
}
|
|
if ($chckBox.length && !$chckBox.prop('checked')) {
|
|
$chckBox.prop('checked', true);
|
|
$chckBox.trigger('change');
|
|
}
|
|
|
|
},
|
|
/**
|
|
* check particular checkbox input
|
|
* @param {string} id
|
|
* @param {string} name
|
|
* @public
|
|
*/
|
|
check: function (id, name) {
|
|
var self = this,
|
|
$chckBox;
|
|
if (name == 'th') {
|
|
|
|
$chckBox = $('#tid_' + self.opt.prefix + id, self.$modalInst);
|
|
} else if (name == 'tg') {
|
|
$chckBox = $('#tgid_' + self.opt.prefix + 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
|
|
* @private
|
|
*/
|
|
_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_' + self.opt.prefix + ui.item.value + '[name="' + ui.item.name + '"]:checked').length) {
|
|
firstTime = false;
|
|
}
|
|
// ban of repeating execution
|
|
if (firstTime) { // konec
|
|
var $checkbox = $('#tid_' + self.opt.prefix + 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.placeComplete({
|
|
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.placeComplete('search', "");
|
|
firstComplete = false;
|
|
} else {
|
|
|
|
self.$inputFilter.placeComplete('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.placeComplete("destroy");
|
|
firstComplete = true;
|
|
}
|
|
}
|
|
return false;
|
|
}).click(function () {
|
|
return false;
|
|
});
|
|
|
|
},
|
|
/**
|
|
* render first level sublist
|
|
* @param {Object} dataObj
|
|
* @param {number|string} tmplId
|
|
* @param {function} handler
|
|
* @private
|
|
*/
|
|
_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);
|
|
},
|
|
/**
|
|
* if there is no children element in list, loads list that is parent to children element
|
|
* @param {Object} data
|
|
* @param {number|string} handler
|
|
* @param {function} counter
|
|
* @private
|
|
*/
|
|
_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
|
|
* @param {number} length
|
|
* @function
|
|
*/
|
|
handlerParent = function () {
|
|
$waiter.hide();
|
|
counter || counter === 0 ? handler(counter) : handler();
|
|
};
|
|
$waiter.show();
|
|
|
|
|
|
optObj = {
|
|
name: dataObj.name,
|
|
id: dataObj.id
|
|
};
|
|
sublistTemplateId = $('#tid_' + self.opt.prefix + dataObj.id).closest('.level').children('.trigger').attr('data-template-id');
|
|
self._renderSublist(optObj, sublistTemplateId, handlerParent);
|
|
|
|
|
|
},
|
|
/**
|
|
* destroy tag and clear tags block.for dna.clone definition see dnajs.org
|
|
* @param {string} checkboxId
|
|
* @private
|
|
*/
|
|
_destroyTag: function (checkboxId, outer) {
|
|
var self = this;
|
|
if (self.itemsSelected[checkboxId]) {
|
|
dna.destroy(self.itemsSelected[checkboxId]);
|
|
|
|
}
|
|
if (self.tagsBoxItems[checkboxId]) {
|
|
dna.destroy(self.tagsBoxItems[checkboxId]);
|
|
|
|
}
|
|
},
|
|
/**
|
|
* for dna.clone definition see dnajs.org
|
|
* @param {number} checkboxId
|
|
* @param {Object} tplObj
|
|
* @private
|
|
*/
|
|
_addTag: function (checkboxId, tplObj) {
|
|
var self = this;
|
|
self.itemsSelected[checkboxId] = dna.clone(self.opt.selectedItemTemplate, tplObj);
|
|
self.tagsBoxItems[checkboxId] = dna.clone(self.opt.tagsBoxId, tplObj);
|
|
self._refreshLabel();
|
|
if(getObjectLength(self.itemsSelected)){
|
|
$(EXPO.events.feed.DOMapplyButton).show();
|
|
$(EXPO.events.feed.DOMhint).hide();
|
|
}
|
|
},
|
|
/**
|
|
* hide or show sublists according active selected link
|
|
* @param {*|jQuery|HTMLElement} $sublist
|
|
* @param {*|jQuery|HTMLElement} $this
|
|
* @private
|
|
*/
|
|
_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');
|
|
}
|
|
|
|
},
|
|
/**
|
|
* reset all selected items, uncheck all selected checkboxes
|
|
* @public
|
|
*/
|
|
resetList: function () {
|
|
var self = this;
|
|
for (var key in self.itemsSelected) {
|
|
if (self.itemsSelected.hasOwnProperty(key)) {
|
|
$('#'+key, self.$selfContainer).prop('checked', false).closest('.custom-radio-check').removeClass('active');
|
|
|
|
dna.destroy(self.itemsSelected[key]);
|
|
dna.destroy(self.tagsBoxItems[key]);
|
|
|
|
}
|
|
}
|
|
$('.level.active',this.$modal).removeClass('active');
|
|
this._refreshLabel();
|
|
|
|
this.$selectedItemsWrap.removeClass('visible');
|
|
},
|
|
/**
|
|
* render label text, if there is no selected element then text will be default
|
|
* @private
|
|
*/
|
|
_refreshLabel: function () {
|
|
var oLength = this.$selectedItemsWrap.children().length;
|
|
if (oLength){
|
|
this.$label.text(this.$label.attr('data-selected'));
|
|
}else{
|
|
this.$label.text(this.$label.attr('data-default'));
|
|
|
|
}
|
|
},
|
|
// кнопка применить
|
|
applyHandler: function (it) {
|
|
EXPO.events.feed.modalWindow.close();
|
|
|
|
},
|
|
/**
|
|
* select particular item and render its tag and check checkbox
|
|
* @param {Object} item
|
|
* @public
|
|
*/
|
|
selectTag:function (item) {
|
|
//check of repeating execution
|
|
var firstTime = true,
|
|
self = this,
|
|
waitHandler = function () {
|
|
self.isReceived = false;
|
|
if(!item.children){
|
|
|
|
for (var prop in self.itemsSelected) {
|
|
if (prop == 'tid_'+ self.opt.prefix+item.id){
|
|
firstTime = false;
|
|
}
|
|
|
|
}
|
|
if($('#tid_'+ self.opt.prefix+item.id+':checked').length){
|
|
firstTime = false;
|
|
}
|
|
if(firstTime){
|
|
self.check(item.id, item.name);
|
|
self.isReceived = true;
|
|
}else{
|
|
$('#tid_'+ self.opt.prefix + item.id).prop('checked', true);
|
|
$('#tid_'+ self.opt.prefix + item.id).trigger('change');
|
|
self.isReceived = true;
|
|
|
|
}
|
|
}else{
|
|
if($('#tgid_'+ self.opt.prefix+item.children.id).length){
|
|
firstTime = false;
|
|
}
|
|
//Если выбран родитель
|
|
if($('#tid_'+ self.opt.prefix+item.id+':checked').length){
|
|
firstTime = false;
|
|
}
|
|
if(firstTime) {
|
|
|
|
self._loadParentTree({name: item.name, id: item.id}, function () {
|
|
self.check(item.children.id, item.children.name);
|
|
self.isReceived = true;
|
|
|
|
});
|
|
}else if(!$('#tgid_'+ self.opt.prefix+item.id+':checked').length){
|
|
|
|
$('#tgid_'+ self.opt.prefix + item.children.id).prop('checked', true);
|
|
$('#tgid_'+ self.opt.prefix + item.children.id).trigger('change');
|
|
self.isReceived = true;
|
|
|
|
}
|
|
}
|
|
|
|
};
|
|
this.wait(waitHandler);
|
|
},
|
|
/**
|
|
* waits so far the previous request will be executed and execute a method
|
|
* @param {function} method
|
|
* @param {Object|Array} args
|
|
* @public
|
|
*/
|
|
wait:function(method, args) {
|
|
var self = this,
|
|
waitImages,
|
|
waitHandler = function(self, method, args) {
|
|
if (self.isReceived) {
|
|
if (args) {
|
|
method(args);
|
|
}
|
|
else{
|
|
method();
|
|
}
|
|
clearInterval(waitImages);
|
|
}
|
|
};
|
|
waitImages = setInterval(function() {waitHandler(self, method, args)}, 100);
|
|
}
|
|
|
|
|
|
};
|
|
|
|
/**
|
|
* Constructor for modal window 'select place'
|
|
* @param {Object} options
|
|
* @constructor
|
|
*/
|
|
var PlacesModal = function (options) {
|
|
/**
|
|
* object properties
|
|
* @type {Object}
|
|
*/
|
|
this.opt = options;
|
|
var self = this,
|
|
$modal = $('#' + self.opt.id),
|
|
$checkBox = $('input[type="checkbox"]', $modal),
|
|
$selectedItemsWrap = $('#'+this.opt.selectedItemsContainer, $modal),
|
|
DOMTagsWrapper = $('#'+this.opt.selectedItemsContainer, $modal)[0],
|
|
$modalTrigger = $('#' + self.opt.modalTrigger),
|
|
applyBtnClass = self.opt.applyBtnClass,
|
|
idPrefix = 'id_',
|
|
DOMfilterBox = document.getElementById(self.opt.bodyId),
|
|
|
|
/**
|
|
* set trigger link text under the search field
|
|
* @function
|
|
*/
|
|
triggerSetText = function () {
|
|
var selectedString,
|
|
cutLength = 16;
|
|
};
|
|
/**
|
|
* current template instances
|
|
* @type {Object}
|
|
*/
|
|
this.curDNA = {};
|
|
/**
|
|
* place modal list items that had selected
|
|
* in modal window
|
|
* @type {Object}
|
|
*/
|
|
this.itemsSelected = {};
|
|
/**
|
|
* place modal list items that had selected
|
|
* on page itself
|
|
* @type {Object}
|
|
*/
|
|
this.tagsBoxItems = {};
|
|
this.selectedWrap = $selectedItemsWrap;
|
|
this.$selfContainer = $modal;
|
|
this.$modal = $modal;
|
|
this.idPrefix = idPrefix;
|
|
/**
|
|
* flag for management of turn of asynchronous requests
|
|
* @type {boolean}
|
|
*/
|
|
this.isReceived = true;
|
|
/**
|
|
* label span element that contain short description for active filter
|
|
* @type {*|jQuery|HTMLElement}
|
|
*/
|
|
this.$label = $(document.getElementById(this.opt.labelId));
|
|
|
|
/**
|
|
* Jquery object of filtering input (autocomplete input)
|
|
* @type {*|jQuery|HTMLElement}
|
|
*/
|
|
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 = com.closest(that, 'level'),
|
|
DOMParentCheckbox = DOMParent.querySelector('.csb-menu-input');
|
|
$('.csb-menu-input', $sublist).each(function () {
|
|
var DOMCheckboxWrap = com.closest(this, 'custom-radio-check');
|
|
if (!this.selected) {
|
|
|
|
if (DOMParentCheckbox.checked) {
|
|
this.checked = true;
|
|
com.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 = com.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 = com.closest(this, itemClass),
|
|
|
|
DOMParentItem = com.hasClass(DOMParentRow, highestItemClass) == false?com.closest(DOMParentRow.parentNode, itemClass):DOMParentRow,
|
|
DOMParentCheckbox = DOMParentItem.querySelector('.'+checkboxClass),
|
|
DOMSublist = DOMParentItem.querySelector('.'+sublistClass),
|
|
DOMSublistInner = DOMParentRow.querySelector('.'+sublistClass),
|
|
DOMHighestItem = com.closest(this, highestItemClass),
|
|
DOMHighestCheckbox = DOMHighestItem.querySelector('.'+checkboxClass),
|
|
DOMHighestSublist = DOMHighestItem.querySelector('.'+sublistClass),
|
|
|
|
selectSublist = function (it) {
|
|
var DOMParentItem = com.closest(it, itemClass) || this,
|
|
DOMSublist = DOMParentItem.querySelector('.'+sublistClass);
|
|
$('.'+checkboxClass, DOMSublist).each(function () {
|
|
selectItem(this);
|
|
});
|
|
|
|
},
|
|
unSelectSublist = function (it) {
|
|
var DOMParentItem = com.closest(it, itemClass) || this,
|
|
DOMSublist = DOMParentItem.querySelector('.'+sublistClass);
|
|
$('.'+checkboxClass, DOMSublist).each(function () {
|
|
unSelectItem(this);
|
|
|
|
});
|
|
|
|
},
|
|
selectParent = function (it) {
|
|
var DOMParentRow = com.closest(it, itemClass),
|
|
DOMParentItem;
|
|
if(com.hasClass(DOMParentRow,'level1')){
|
|
DOMParentItem = DOMParentRow;
|
|
}else{
|
|
DOMParentItem = com.closest(DOMParentRow.parentNode, itemClass);
|
|
}
|
|
|
|
com.addClass(DOMParentItem.querySelector('.'+fakeCheckboxClass), activeClass);
|
|
DOMParentItem.querySelector('.'+checkboxClass).checked = true;
|
|
|
|
//it.selected = true;
|
|
|
|
},
|
|
unSelectParent = function (it) {
|
|
var DOMParentRow = com.closest(it, itemClass),
|
|
DOMParentItem = com.closest(DOMParentRow.parentNode, itemClass) || DOMParentRow;
|
|
|
|
com.removeClass(DOMParentItem.querySelector('.'+fakeCheckboxClass), activeClass);
|
|
DOMParentItem.querySelector('.'+checkboxClass).checked = false;
|
|
//it.checked = false;
|
|
|
|
},
|
|
selectItem = function (it) {
|
|
var itFakeCheckbox = com.closest(it, fakeCheckboxClass);
|
|
com.addClass(itFakeCheckbox, activeClass);
|
|
it.checked = true;
|
|
com.addClass(DOMParentItem,activeClass);
|
|
com.removeClass(DOMSublist,'hidden');
|
|
|
|
},
|
|
unSelectItem = function (it) {
|
|
var itFakeCheckbox = com.closest(it, fakeCheckboxClass),
|
|
DOMitem = com.closest(it, itemClass);
|
|
com.removeClass(itFakeCheckbox, activeClass);
|
|
it.checked = false;
|
|
// if there is children items
|
|
if(DOMitem.querySelector('.'+sublistClass) && !com.hasClass(DOMitem,highestItemClass)){
|
|
unSelectSublist(it);
|
|
}
|
|
},
|
|
allChildrenSelected = function () {
|
|
//var DOMselected = DOMSublist.querySelectorAll('.'+checkboxClass+':checked'),
|
|
var DOMSublistParent = com.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;
|
|
}
|
|
},
|
|
allHighestSelected = function () {
|
|
//var DOMselected = DOMSublist.querySelectorAll('.'+checkboxClass+':checked'),
|
|
var $selected = $(DOMHighestSublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked'),
|
|
selectedCount = $selected.length,
|
|
allCount = $(DOMHighestSublist).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 = com.closest(it,sublistClass);
|
|
var DOMItem = com.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<DOMAllTags.length; t++){
|
|
tmp = DOMAllTags[t].querySelector('.'+tagButtonClass).getAttribute(tagIdAttribute);
|
|
if(tmp != '~~id~~'){
|
|
ARRAllTagsIds.push(tmp);
|
|
}
|
|
}
|
|
allTagsLength = ARRAllTagsIds.length;
|
|
sublistIdsLength = ARRSublistIds.length;
|
|
|
|
//если найден дочерний тег то он будет удален, либо текущий тег
|
|
for(i = 0; i < allTagsLength; i++){
|
|
tagId = ARRAllTagsIds[i];
|
|
for(j = 0; j< sublistIdsLength; j++){
|
|
if( tagId == ARRSublistIds[j] ){
|
|
deleteTag(ARRsublist[j]);
|
|
}
|
|
}
|
|
}
|
|
// удаление дубликатов текущего элемента
|
|
for(i = 0; i < allTagsLength; i++){
|
|
tagId = ARRAllTagsIds[i];
|
|
if( tagId == itId){
|
|
deleteTag(it);
|
|
}
|
|
}
|
|
// удаление дочерних тегов 2го уровня
|
|
if(DOMSublistInner.querySelectorAll('.final-tire')){
|
|
$('.'+fakeCheckboxClass+'.'+activeClass, DOMSublistInner.querySelectorAll('.final-tire')).each(function () {
|
|
deleteTag($('.'+checkboxClass,this)[0]);
|
|
|
|
});
|
|
}
|
|
}else{
|
|
// удаление дубликатов текущего элемента
|
|
for(i = 0; i < allTagsLength; i++){
|
|
tagId = ARRAllTagsIds[i];
|
|
if( tagId == itId){
|
|
deleteTag(itId);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
},
|
|
deleteTag = function (it) {
|
|
var id = it.getAttribute('id');
|
|
self._destroyTag(id);
|
|
tagsPanelToggle();
|
|
},
|
|
createTag = function (it) {
|
|
var item = com.closest(it,itemClass),
|
|
tagTrigger = item.querySelector('.'+triggerClass),
|
|
tagText = tagTrigger.innerHTML,
|
|
id = it.getAttribute('id'),
|
|
tagObj = {'id':id,'text':tagText};
|
|
self._addTag(id, tagObj);
|
|
tagsPanelToggle();
|
|
},
|
|
tagsPanelToggle = function () {
|
|
if($selectedItemsWrap.find('.'+tagButtonClass).length && $selectedItemsWrap.find('.'+tagButtonClass)[0].getAttribute(tagIdAttribute) != "~~id~~"){
|
|
$selectedItemsWrap.addClass('visible');
|
|
}else{
|
|
$selectedItemsWrap.removeClass('visible');
|
|
}
|
|
},
|
|
createTagList = function (sublist) {
|
|
var $selected = $(sublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked');
|
|
$selected.each(function () {
|
|
createTag(this);
|
|
});
|
|
|
|
},
|
|
deleteTagList = function () {
|
|
var $selected = $(DOMSublist).children('li').children('.'+fakeCheckboxClass).find('.'+checkboxClass+':checked');
|
|
$selected.each(function () {
|
|
deleteTag(this);
|
|
});
|
|
};
|
|
|
|
|
|
|
|
|
|
//make fake checkbox active\passive
|
|
/**
|
|
* if modala is not in strict mode ( enable popping from children categories to parent)
|
|
*/
|
|
if(!self.strictMode){
|
|
|
|
if(this.checked){
|
|
if($(DOMSublistInner).find('.'+checkboxClass)[0]){
|
|
|
|
if(DOMSublistInner && $(DOMSublistInner).find('.'+checkboxClass)[0].value != '~~id~~'){
|
|
refreshTags(this);
|
|
}
|
|
}
|
|
//если выбраны все дочерние
|
|
if(allChildrenSelected()){
|
|
selectParent(this);
|
|
selectItem(this);
|
|
refreshTags(DOMParentCheckbox);
|
|
createTag(DOMParentCheckbox);
|
|
deleteTagList(DOMSublist);
|
|
if(DOMParentCheckbox.getAttribute('id')== DOMHighestCheckbox.getAttribute('id') && !DOMHighestCheckbox.checked){
|
|
selectItem(DOMHighestCheckbox);
|
|
refreshTags(DOMHighestCheckbox);
|
|
createTag(DOMHighestCheckbox);
|
|
//если только что вклбченный чекбокс дополняет остальные включенные чекбоксы, то включается самый верхний чекбокс
|
|
}else if(allHighestSelected()){
|
|
selectItem(DOMHighestCheckbox);
|
|
refreshTags(DOMHighestCheckbox);
|
|
createTag(DOMHighestCheckbox);
|
|
}
|
|
}else{
|
|
selectItem(this);
|
|
refreshTags(this);
|
|
createTag(this);
|
|
}
|
|
//выбрать все дочерние
|
|
if(DOMSublistInner){
|
|
selectSublist(this);
|
|
}
|
|
|
|
}else{
|
|
|
|
//Если выбран родитель
|
|
if(parentSelected()){
|
|
unSelectParent(this);
|
|
unSelectItem(this);
|
|
refreshTags(DOMParentCheckbox);
|
|
deleteTag(DOMParentCheckbox);
|
|
createTagList(DOMSublist);
|
|
if(DOMHighestCheckbox.checked){
|
|
|
|
unSelectItem(DOMHighestCheckbox);
|
|
deleteTag(DOMHighestCheckbox);
|
|
createTagList(DOMHighestSublist);
|
|
}
|
|
|
|
}else{
|
|
unSelectItem(this);
|
|
refreshTags(this);
|
|
deleteTag(this);
|
|
}
|
|
//убрать все дочерние
|
|
if(DOMSublistInner){
|
|
unSelectSublist(this);
|
|
refreshTags(this);
|
|
}
|
|
|
|
}
|
|
}else{
|
|
if(this.checked){
|
|
selectItem(this);
|
|
refreshTags(this);
|
|
createTag(this);
|
|
}else{
|
|
unSelectItem(this);
|
|
refreshTags(this);
|
|
deleteTag(this);
|
|
}
|
|
}
|
|
triggerSetText();
|
|
});
|
|
/**
|
|
* delete tag button behavior
|
|
*/
|
|
$('.' + self.opt.deleteTagClass, $modal).on('click', function () {
|
|
var checkboxId = $(this).attr('data-checkbox-id'),
|
|
$uncheckBoxes = $('#' + checkboxId);
|
|
$uncheckBoxes.prop('checked', false);
|
|
$uncheckBoxes.trigger('change');
|
|
//dna.destroy(self.itemsSelected[checkboxId]);
|
|
//self._destroyTag(checkboxId);
|
|
self._refreshLabel();
|
|
if (!$selectedItemsWrap.children('.dna-clone').length) {
|
|
$selectedItemsWrap.removeClass('visible');
|
|
}
|
|
return false;
|
|
});
|
|
$('.del-on-page').on('click',function () {
|
|
var dataCheckboxId = $(this).attr('data-checkbox-id');
|
|
$('.' + self.opt.deleteTagClass+'[data-checkbox-id="'+dataCheckboxId+'"]', $modal).trigger('click');
|
|
});
|
|
/**
|
|
* clear all button behavior
|
|
*/
|
|
$('.clear', $modal).on('click', function () {
|
|
self.resetList();
|
|
return false;
|
|
});
|
|
/**
|
|
* sublist behaivor
|
|
*/
|
|
$('.q-sel a', $modal).on('click', function () {
|
|
var $this = $(this),
|
|
name = $this.attr('data-name'),
|
|
id = $this.attr('data-id'),
|
|
ajaxObj = {name: name, id: id},
|
|
ajaxHandler = function (data) {
|
|
self._loadParentTree(data, function () {
|
|
self._checkCheckBox(id);
|
|
});
|
|
|
|
};
|
|
getRequest(ajaxObj, self.opt.getParentUrl, ajaxHandler);
|
|
return false;
|
|
});
|
|
$('.' + applyBtnClass, $modal).on('click', function () {
|
|
self.applyHandler(this);
|
|
return false;
|
|
});
|
|
$('.'+self.opt.clearAllButtonClass,$modal).on('click', function (e) {
|
|
e.preventDefault();
|
|
self.resetList();
|
|
return false;
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
/**
|
|
* methods for modal window object
|
|
* @type {{_getAjax: Function, _renderSublist: Function, _renderNested: Function, _checkCheckBox: Function, selectTag: Function, wait: Function, check: Function, _slideToggle: Function, _destroyTag: Function, _addTag: Function, resetList: Function, _autocompleteInit: Function, _loadParentTree: Function, applyHandler: Function, isSelected: Function}}
|
|
*/
|
|
PlacesModal.prototype = {
|
|
/**
|
|
* some kind of wrapper in top of jquery.AJAx
|
|
* @param {Object|string} dataToSend
|
|
* @param {function} handler
|
|
* @private
|
|
*/
|
|
_getAjax: function (dataToSend, handler) {
|
|
var self = this;
|
|
if (!dataToSend) {
|
|
dataToSend = '';
|
|
}
|
|
$.ajax({
|
|
type: 'GET',
|
|
url: self.opt.ajaxUrl,
|
|
data: dataToSend,
|
|
success: function (data) {
|
|
if (typeof handler == 'function') {
|
|
self.rawData = data;
|
|
handler(data);
|
|
} else {
|
|
self.rawData = data;
|
|
return data;
|
|
|
|
}
|
|
}
|
|
});
|
|
},
|
|
/**
|
|
* render first level sublist (require dna.js template engine)
|
|
* @param {Object} dataObj
|
|
* @param {string} tmplId
|
|
* @param {function} handler
|
|
* @private
|
|
*/
|
|
_renderSublist: function (dataObj, tmplId, handler) {
|
|
var self = this,
|
|
index = 0,
|
|
template = tmplId + '-sub',
|
|
ajaxHandler = function (data) {
|
|
if (data.length) {
|
|
|
|
self.curDNA[template] = {};
|
|
|
|
// for dna.clone definition see dnajs.org
|
|
for (index; index < data.length; index++) {
|
|
self.curDNA[template][data[index].id] = dna.clone(tmplId, data[index]);
|
|
|
|
}
|
|
$('.' + tmplId).parents('.level1').addClass('active');
|
|
handler(data.length);
|
|
} else {
|
|
$waiter.hide();
|
|
}
|
|
};
|
|
self._getAjax(dataObj, ajaxHandler);
|
|
},
|
|
/**
|
|
* render second level sublist
|
|
* @param {Object} dataObj
|
|
* @param {function} handler
|
|
* @param {string} template
|
|
* @param {number} item
|
|
* @private
|
|
*/
|
|
_renderNested: function (dataObj, handler, template, item) {
|
|
var self = this,
|
|
Uri = Json2URI(dataObj),
|
|
ajaxHandler = function (data) {
|
|
if(data.length){
|
|
dna.load(template, (self.opt.ajaxUrl + Uri),{callback: function () {
|
|
handler(data.length);
|
|
},container:self.curDNA[template][item]});
|
|
|
|
}
|
|
};
|
|
self._getAjax(dataObj, ajaxHandler);
|
|
},
|
|
/**
|
|
* check particular checkbox input
|
|
* @param {number} id
|
|
* @private
|
|
*/
|
|
_checkCheckBox: function (id) {
|
|
var self = this,
|
|
$chckBox = $('#id_'+self.opt.prefix + id, self.$selfContainer);
|
|
if ($chckBox.length && !$chckBox.prop('checked')) {
|
|
$chckBox.prop('checked', true);
|
|
$chckBox.trigger('change');
|
|
}
|
|
|
|
},
|
|
/**
|
|
* select particular item and render its tag and check checkbox
|
|
* @param {Object} item
|
|
* @public
|
|
*/
|
|
selectTag: function (item) {
|
|
//check of repeating execution
|
|
var firstTime = true,
|
|
self = this,
|
|
waitHandler = function () {
|
|
for (var prop in self.curDNA) {
|
|
for (var prop2 in self.curDNA[prop]) {
|
|
if (prop2 == item.id) {
|
|
firstTime = false;
|
|
}
|
|
|
|
}
|
|
}
|
|
if ($('#id_'+ self.opt.prefix + item.id + ':checked').length) {
|
|
firstTime = false;
|
|
$('#id_'+ self.opt.prefix + item.id + ':checked').trigger('change');
|
|
}
|
|
// ban of repeating execution
|
|
if (firstTime) { // konec
|
|
self.isReceived = false;
|
|
var $checkbox = $('#id_'+ self.opt.prefix + item.id),
|
|
requestObj, requestName,
|
|
treeLoadHandler = function (data) {
|
|
// make checkboxes selected after loading
|
|
|
|
self._loadParentTree(data, function () {
|
|
self._checkCheckBox(item.id);
|
|
self.isReceived = true;
|
|
});
|
|
$checkbox = $('#id_'+ self.opt.prefix + item.id);
|
|
};
|
|
// load tree related to selected item
|
|
if (!$checkbox.length) {
|
|
|
|
requestObj = {
|
|
id: item.id,
|
|
name: item.name
|
|
};
|
|
|
|
getRequest(requestObj, self.opt.getParentUrl, treeLoadHandler);
|
|
|
|
|
|
} else {
|
|
$checkbox.prop('checked', true);
|
|
$checkbox.trigger('change');
|
|
self.isReceived = true;
|
|
}
|
|
|
|
} else {
|
|
$('#id_'+ self.opt.prefix + item.id).prop('checked', true);
|
|
$('#id_'+ self.opt.prefix + item.id).trigger('change');
|
|
}
|
|
};
|
|
this.wait(waitHandler);
|
|
},
|
|
/**
|
|
* waits so far the previous request will be executed and execute a method
|
|
* @param {function} method
|
|
* @param {Object|Array} args
|
|
* @public
|
|
*/
|
|
wait: function (method, args) {
|
|
var self = this,
|
|
waitImages,
|
|
waitHandler = function (self, method, args) {
|
|
if (self.isReceived) {
|
|
if (args) {
|
|
method(args);
|
|
}
|
|
else {
|
|
method();
|
|
}
|
|
clearInterval(waitImages);
|
|
}
|
|
};
|
|
waitImages = setInterval(function () {
|
|
waitHandler(self, method, args)
|
|
}, 100);
|
|
},
|
|
/**
|
|
* check particular checkbox input
|
|
* @param {number} id
|
|
* @param {string} tagText
|
|
* @public
|
|
*/
|
|
check: function (id, tagText) {
|
|
var self = this,
|
|
$chckBox = $('#id_' + id, self.$selfContainer),
|
|
tagObj = {};
|
|
if ($chckBox.length && !$chckBox.prop('checked')) {
|
|
|
|
$chckBox.prop('checked', true);
|
|
$chckBox.trigger('change');
|
|
}
|
|
|
|
},
|
|
/**
|
|
* hide or show sublists according active selected link
|
|
* @param $sublist
|
|
* @param $this
|
|
* @private
|
|
*/
|
|
_slideToggle: function ($sublist, $this) {
|
|
if ($sublist.hasClass('hidden')) {
|
|
$this.addClass('active');
|
|
$sublist.removeClass('hidden');
|
|
} else {
|
|
$this.removeClass('active');
|
|
//$sublist.addClass('hidden').find('ul').addClass('hidden');
|
|
$sublist.addClass('hidden').find('ul');
|
|
}
|
|
|
|
},
|
|
/**
|
|
* for dna.clone definition see dnajs.org
|
|
* @param {string} checkboxId
|
|
* @private
|
|
*/
|
|
_destroyTag: function (checkboxId) {
|
|
var self = this;
|
|
if (self.itemsSelected[checkboxId]) {
|
|
dna.destroy(self.itemsSelected[checkboxId]);
|
|
|
|
}
|
|
if (self.tagsBoxItems[checkboxId]) {
|
|
dna.destroy(self.tagsBoxItems[checkboxId]);
|
|
|
|
}
|
|
//this._refreshLabel();
|
|
},
|
|
/**
|
|
* for dna.clone definition see dnajs.org
|
|
* @param {string} checkboxId
|
|
* @param tplObj
|
|
* @private
|
|
*/
|
|
_addTag: function (checkboxId, tplObj) {
|
|
var self = this;
|
|
self.itemsSelected[checkboxId] = dna.clone(self.opt.selectedItemTemplate, tplObj);
|
|
self.tagsBoxItems[checkboxId] = dna.clone(self.opt.tagsBoxId, tplObj);
|
|
this._refreshLabel();
|
|
if(getObjectLength(self.itemsSelected)){
|
|
$(EXPO.events.feed.DOMapplyButton).show();
|
|
$(EXPO.events.feed.DOMhint).hide();
|
|
|
|
}
|
|
|
|
},
|
|
/**
|
|
* reset all checkboxes and clean tag wrapper
|
|
* @public
|
|
*/
|
|
resetList: function () {
|
|
var self = this;
|
|
for (var key in self.itemsSelected) {
|
|
if (self.itemsSelected.hasOwnProperty(key)) {
|
|
$('#'+key, self.$selfContainer).prop('checked', false).closest('.custom-radio-check').removeClass('active');
|
|
|
|
dna.destroy(self.itemsSelected[key]);
|
|
dna.destroy(self.tagsBoxItems[key]);
|
|
}
|
|
}
|
|
$('.level.active',this.$modal).removeClass('active');
|
|
this._refreshLabel();
|
|
this.selectedWrap.removeClass('visible');
|
|
},
|
|
/**
|
|
* initiliazing and setup autocomplete field for places list
|
|
* @private
|
|
*/
|
|
_autocompleteInit: function () {
|
|
var self = this, dataObj, text, form = self.$inputFilter.attr('data-form'), index,
|
|
$completeWrap = $('#' + self.opt.autoCompleteId),
|
|
firstComplete = true,
|
|
/**
|
|
* after tag is select
|
|
* @param {Object} event Jquery event object
|
|
* @param {Object} ui selected item object
|
|
*/
|
|
selectTag = function (event, ui) {
|
|
//check of repeating execution
|
|
$waiter.show();
|
|
var firstTime = true,
|
|
$checkbox = $('#id_' + self.opt.prefix + ui.item.value);
|
|
for (var prop in self.curDNA) {
|
|
for (var prop2 in self.curDNA[prop]) {
|
|
if (prop2 == ui.item.value) {
|
|
firstTime = false;
|
|
}
|
|
|
|
}
|
|
}
|
|
// if item is alreday selected
|
|
if ($('#id_' + self.opt.prefix + ui.item.value + ':checked').length) {
|
|
firstTime = false;
|
|
}
|
|
// ban of repeating execution
|
|
if (firstTime) { // konec
|
|
var requestObj, requestName,
|
|
treeLoadHandler = function (data) {
|
|
// make checkboxes selected after loading
|
|
self._loadParentTree(data, function () {
|
|
self._checkCheckBox(ui.item.value);
|
|
|
|
});
|
|
$checkbox = $('#id_' + self.opt.prefix + ui.item.value);
|
|
};
|
|
// 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 {
|
|
$checkbox.prop('checked', true);
|
|
$checkbox.trigger('change');
|
|
$waiter.hide()
|
|
}
|
|
|
|
self.$inputFilter.val(ui.item.label);
|
|
}else{
|
|
$checkbox.prop('checked', true);
|
|
$checkbox.trigger('change');
|
|
$waiter.hide()
|
|
}
|
|
},
|
|
/**
|
|
* autocomplete execute after recieving data
|
|
* @param {Object} data recieved from ajax response
|
|
*/
|
|
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,
|
|
/**
|
|
* autocomplete item is selected
|
|
* @param {Object} event jquery event object
|
|
* @param {Object} ui selected item object
|
|
*/
|
|
select: function (event, ui) {
|
|
selectTag(event, ui);
|
|
self.$inputFilter.val('');
|
|
self.$inputFilter.trigger('keyup');
|
|
event.preventDefault();
|
|
}
|
|
});
|
|
self.$inputFilter.autocomplete('search', "");
|
|
firstComplete = false;
|
|
} else {
|
|
|
|
self.$inputFilter.autocomplete('search', "");
|
|
}
|
|
$waiter.hide();
|
|
|
|
};
|
|
// 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) {
|
|
$waiter.show();
|
|
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
|
|
* @param {Object} data - is JSON object with information about parent elements.
|
|
* @param {function} handler - callback function
|
|
* @param {number} counter
|
|
* @private
|
|
*/
|
|
_loadParentTree: function (data, handler, counter) {
|
|
var self = this,
|
|
dataObj = data,
|
|
optObj, sublistTemplateId, nestedObj, nestedSublistTemplateId,
|
|
$midleLevelCheckbox = $('#id_' + self.opt.prefix + dataObj.id),
|
|
/**
|
|
* makes request in order to recieve children list information fires after request for parent list
|
|
* @param {number} length
|
|
* @function
|
|
*/
|
|
handlerNested = function (length) {
|
|
var $checkbox = $('#id_' + self.opt.prefix + dataObj.id),
|
|
index = 0,
|
|
afterAll = function (number) {
|
|
$waiter.hide();
|
|
index++
|
|
if(index == number){
|
|
|
|
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_' + self.opt.prefix + dataObj.id).closest('.level').children('.trigger').attr('data-template-id');
|
|
self._renderNested(nestedObj, afterAll, nestedSublistTemplateId, dataObj.id);
|
|
}
|
|
|
|
},
|
|
/**
|
|
* @function
|
|
*/
|
|
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_' + self.opt.prefix + 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_' + self.opt.prefix + dataObj.id).closest('.level').children('.trigger').attr('data-template-id');
|
|
self._renderSublist(optObj, sublistTemplateId, handlerParent);
|
|
}
|
|
|
|
},
|
|
applyHandler: function (it) {
|
|
EXPO.events.feed.modalWindow.close();
|
|
},
|
|
/**
|
|
* render label text, if there is no selected element then text will be default
|
|
* @private
|
|
*/
|
|
_refreshLabel: function () {
|
|
var oLength = this.selectedWrap.children().length;
|
|
|
|
if (oLength){
|
|
this.$label.text(this.$label.attr('data-selected'));
|
|
}else{
|
|
this.$label.text(this.$label.attr('data-default'));
|
|
|
|
}
|
|
}
|
|
};
|
|
|
|
///////////////////////////
|
|
//инициализация общих свойств
|
|
that.init = function (options) {
|
|
// settings extending
|
|
$.extend(this.opt, options);
|
|
// begin of initialization
|
|
var self = this,
|
|
submitHandler = function () {
|
|
$(self.DOMform).find('input[name="~~name~~"]').remove();
|
|
};
|
|
if(this.opt.searchData != 'None' && this.opt.searchData){
|
|
this.previousSearch = JSON.parse(this.opt.searchData)
|
|
|
|
}
|
|
this.DOMform = document.getElementById(this.opt.formId);
|
|
this.DOMhint = document.getElementById(this.opt.filter.hintId);
|
|
$(this.DOMform).on('submit', function () {
|
|
submitHandler();
|
|
});
|
|
$.widget( "custom.placeComplete", $.ui.autocomplete,{
|
|
_renderItem: function( ul, item ) {
|
|
return $( "<li>" )
|
|
.append( $( "<a>" ).text( item.label) )
|
|
.append('<span class="subj-category"> ('+item.cat+')</span>')
|
|
.appendTo( ul );
|
|
}
|
|
});
|
|
this.DOMapplyButton = document.getElementById(this.opt.applyButtonId);
|
|
this.filterPane = new Filter(this.opt.filter);
|
|
$('#' + this.opt.filter.buttonId).on('click', function () {
|
|
if (com.hasClass(this, self.opt.activeClass)) {
|
|
com.removeClass(this, self.opt.activeClass);
|
|
self.filterPane.hide();
|
|
} else {
|
|
com.addClass(this, self.opt.activeClass);
|
|
self.filterPane.show();
|
|
}
|
|
return false;
|
|
});
|
|
$('#'+self.opt.bodyId+' .' + self.opt.modalTriggerClass).on('click', function (event) {
|
|
event.preventDefault();
|
|
self.modalWindow.pullData(this.getAttribute('href'));
|
|
self.modalWindow.open();
|
|
return false;
|
|
});
|
|
//кнопка применить
|
|
$('#'+self.opt.applyButtonId).on('click', function () {
|
|
$(self.DOMform).submit();
|
|
return false;
|
|
});
|
|
//modal
|
|
//модальное окно
|
|
this.modalWindow = new com.Modal(self.opt.modal);
|
|
//modal windows
|
|
this.placesModal = new PlacesModal(self.opt.place);
|
|
this.subjModal = new SubjectModal(self.opt.subject);
|
|
|
|
// заполнение полей предыдущими значениями
|
|
$(function () {
|
|
if(self.previousSearch.inputs.length){
|
|
$(self.DOMhint).hide();
|
|
for (var i = 0; i < self.previousSearch.inputs.length; i++) {
|
|
// окно выбора тематики
|
|
if (self.previousSearch.inputs[i].name == 'th'){
|
|
self.subjModal.selectTag(self.previousSearch.inputs[i]);
|
|
|
|
// окно выбора мест
|
|
} else if (self.previousSearch.inputs[i].name == 'area'){
|
|
|
|
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]);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
}else{
|
|
$(self.DOMhint).fadeIn();
|
|
}
|
|
//Если выбраны фильтры то появляется кнопка "применить"
|
|
if(getObjectLength(self.placesModal.itemsSelected) || getObjectLength(self.subjModal.itemsSelected) ){
|
|
$(self.DOMapplyButton).show();
|
|
|
|
}
|
|
});
|
|
|
|
};
|
|
return that;
|
|
}());
|
|
}
|
|
|