/** * Created by pavel.handleman@gmail.com on 15.10.2014. * commonly using snippets and functions. this module must be loaded on every page */ 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.settings = {}; //свойства по умолчанию // Валидация форм, каждый объект содержит поля объектов формы и методы работы с формой 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 //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); }); }; var forms = []; $(function () { $('form.validate').each(function () { forms.push(new Validation(this)); }); }); $("input[type='checkbox'], input[type='radio']").customRadioCheck(); }); // methods //инициализация общих свойств that.init = function (options) { $.extend(this.settings, options); var self = this; }; 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; }; return that; }()); }