var EXPO = EXPO || {}; //isolated namespace //общий для всех страниц модуль Функционал общий для всех страниц if (EXPO.common){ console.warn('WARNING: EXPO.common is already defined!'); }else { EXPO.common = (function () { // variables var that = {}; var matches = function(el, selector) { return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector); }; that.opt = {}; //свойства по умолчанию // Валидация форм, каждый объект содержит поля объектов формы и методы работы с формой var Validation = function(obj){ //поля над которыми проводится валидация this.fields = []; //флаг которые опдвтерждает отправку формы. если true то ошибок нет this.allIsClear = false; this.ajaxUrl = obj.getAttribute('action'); this.DOM = obj; this._initFields(); this._eventController(); }; Validation.prototype = { //связывает данные объекта с html кодом _eventController: function () { var self = this; if(this.DOM.addEventListener){ this.DOM.addEventListener("submit", function (event) { self.validate(); event.preventDefault(); return false; }, false); //Modern browsers }else if(this.DOM.attachEvent){ this.DOM.attachEvent('onsubmit', function (event) { self.validate(); event.preventDefault(); return false; }); //Old IE } }, //берет все поля с классом required _initFields: function () { //this.fields = this.DOM.querySelectorAll('.required input'); }, //проводит валидацию, выводит сообщение об ошибках validate: function () { var self = this, formData = $(self.DOM).serialize(), responseData, inputObj ={}, errBoxClass = 'err-message-box', DOMerrBox = self.DOM.querySelector('.'+errBoxClass), errBoxText = DOMerrBox.innerHTML, handler = function (data){ responseData = data; self.unHighlightFields(); if(responseData.success){ if(DOMerrBox){ EXPO.common.removeClass(DOMerrBox, 'active'); } window.location.reload(); }else{ EXPO.common.removeClass(DOMerrBox, 'active'); inputObj ={}; self.fields = []; for(var prop in responseData.errors) { if (!responseData.errors.hasOwnProperty(prop)) continue; if(prop != '__all__'){ inputObj ={'name':prop, 'id':'id_'+prop, 'errorText':responseData.errors[prop]}; //inputObj.name = prop; //inputObj.id = 'id_'+prop; //inputObj.errorText = responseData.errors[prop]; self.fields.push(inputObj); }else{ if(DOMerrBox){ EXPO.common.addClass(DOMerrBox, 'active'); if(errBoxText.indexOf(responseData.errors[prop]) < 0) { DOMerrBox.insertAdjacentHTML('beforeend', responseData.errors[prop]+' '); } } } } self.highliteFields(); } }; self.unHighlightFields(); EXPO.common.postRequest(formData, self.ajaxUrl,handler); }, //подсвечивает неправильно введенные поля, highliteFields: function () { var DOMfield, DOMfieldWrap; for(var i = 0; i < this.fields.length; i++){ DOMfield = this.DOM.querySelector('#'+ this.fields[i].id); DOMfieldWrap = DOMfield.parentNode; EXPO.common.addClass(DOMfieldWrap,'required'); EXPO.common.addClass(DOMfieldWrap,'err'); } }, unHighlightFields: function () { var DOMfield, DOMfieldWrap; for(var i = 0; i < this.fields.length; i++){ DOMfield = this.DOM.querySelector('#'+ this.fields[i].id); DOMfieldWrap = DOMfield.parentNode; EXPO.common.removeClass(DOMfieldWrap,'required'); EXPO.common.removeClass(DOMfieldWrap,'err'); } }, submit: function () { } }; //dependences that.forms = []; $(function () { $('form.validate').each(function () { that.forms.push(new Validation(this)); }); }); //private $(function () { /* Нестандартное оформление для поля checkbox */ $.fn.customRadioCheck = function () { return $(this).each(function () { var $el = $(this); var type = $el.attr("type"); var $label = $el.closest("label"); var $customCheckbox = $el.wrap("").parent(); $label.addClass("custom-radio-check"); function setState () { if (type == 'radio') { var name = $el.attr('name'); var $radios = $('input[type="radio"]').filter('[name="' + name + '"]'); $radios.each(function () { var $container = $(this).closest('.custom-radio'); $container.removeClass('checked'); if ($(this).is(':checked')) { $container.addClass('checked'); } }); } else { if ($el.prop("checked")) { $customCheckbox.addClass("checked"); } else { $customCheckbox.removeClass("checked"); } } $el.trigger('blur'); } setState(); $el.on("change", setState); }); }; $("input[type='checkbox'], input[type='radio']").customRadioCheck(); // add to calendar button click event functional }); // methods //инициализация общих свойств that.init = function (options) { $.extend(this.opt, options); var self = this, addClass = this.opt.addCalendarClass, remClass = this.opt.removeCalendarClass, addText = this.opt.addCalendarText, remText = this.opt.removeCalendarText, validErrorClass = self.opt.staticValidation.errorClass, validContainerClass = self.opt.staticValidation.containerClass, $staticFields, blobClass = self.opt.staticValidation.blobClass; $(function () { $staticFields = $('.'+validErrorClass); $('.'+addClass+', .'+remClass).on('click', function(event){ addText = self.opt.addCalendarText; remText = self.opt.removeCalendarText; event.preventDefault(); var $this = $(this); var url = $this.attr('href'); $.get(url, function(data){ if (data.not_authorized){ $.fancybox.open('#'+self.opt.loginModalId); } else{ if(data.success){ if(data.in){ $this.removeClass(addClass).addClass(remClass).text(remText); } else{ $this.removeClass(remClass).addClass(addClass).text(addText); } } } }); }); /** * static validation (non Ajax) on form fields */ if($staticFields.length){ $staticFields.find('input:text').on('keyup', function () { if($.trim($(this).val()) != ''){ $(this).closest('.'+validErrorClass).removeClass(validErrorClass); }else{ $(this).closest('.'+validContainerClass).addClass(validErrorClass); } }) } }); }; that.hasClass = function (DOM, className) { if (DOM.classList) return DOM.classList.contains(className); else return new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className); }; that.addClass = function (DOM, className) { if (!that.hasClass(DOM, className)) { if (DOM.classList) DOM.classList.add(className); else DOM.className += ' ' + className; } return DOM; }; that.removeClass = function (DOM, className) { var newClass = ' ' + DOM.className.replace(/[\t\r\n]/g, ' ') + ' '; if (that.hasClass(DOM, className)) { if (DOM.classList){ DOM.classList.remove(className); }else{ while (newClass.indexOf( ' ' + className + ' ') >= 0) { newClass = newClass.replace(' ' + className + ' ', ' '); } DOM.className = newClass.replace(/^\s+|\s+$/g, ' '); } } return DOM; }; //Jquery .closest analog for pure js that.closest = function(el, className) { var fn = function(className){ return that.hasClass(el, className); }; while (el) { if (fn(className)) return el; el = el.parentNode; } }; //JQUERY .children alternative ie 9+ that.children = function (elm, sel){ var ret = [], i = 0, l = elm.childNodes.length; for (var i; i < l; ++i){ if (matches(elm.childNodes[i], sel)){ ret.push(elm.childNodes[i]); } } return ret; }; // MEtHOD for make ajax GET Jquery.ajax.request and launch handler if exist or return data that.postRequest = function (dataToSend,url,handler) { if(!dataToSend){ dataToSend = ''; } $.ajax({ type: 'POST', url: url, data:dataToSend, success: function(data) { if(typeof handler == 'function'){ console.log('data recieved:'); console.log(data); console.log(JSON.stringify(data)); handler(data); } else{ return data; } } }); }; that.getRequest = function (dataToSend,url,handler) { if(!dataToSend){ dataToSend = ''; } $.ajax({ type: 'GET', url: url, data:dataToSend, success: function(data) { if(typeof handler == 'function'){ console.log('data recieved:'); console.log(data); console.log(JSON.stringify(data)); handler(data); } else{ return data; } } }); }; /** * prototype of a modal window - general for all * @param options * @constructor */ that.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(); } }); }; that.Modal.prototype = { /** * @param {string} selector * @public */ pullData: function (selector) { this.id = selector.substr(1); $(selector).show().siblings().hide(); this.refresh(); }, /** * open and show modal * @public */ open: function () { $(this.DOMwrap).fadeIn(); that.addClass(document.body, 'ov-hidden'); }, /** * close and hide modal window * @public */ close: function () { $(this.DOMwrap).fadeOut(); that.removeClass(document.body, 'ov-hidden'); }, /** * initialize modal window * @public */ 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'; } } return that; }()); }