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.
 
 
 
 
 
 

579 lines
16 KiB

var EXPO = EXPO || {}; //isolated namespace
//общий для всех страниц модуль Функционал общий для всех страниц
if (EXPO.common){
console.warn('WARNING: EXPO.common is already defined!');
}else {
EXPO.common = (function () {
/**
* private (visible inside this module only) variables
*/
/**
* @type {Object} - module API interafce realization
*/
var that = {};
/**
* helper for this.children
* @param {HTMLElement} el
* @param selector
* @returns {*}
*/
var matches = function(el, selector) {
return (el.matches || el.matchesSelector || el.msMatchesSelector || el.mozMatchesSelector || el.webkitMatchesSelector || el.oMatchesSelector).call(el, selector);
},
$waiter;
/**
* @type {Object} default setting
*/
that.opt = {}; //свойства по умолчанию
// Валидация форм, каждый объект содержит поля объектов формы и методы работы с формой
/**
* Form validation mechanism
* @param {*|jQuery|HTMLElement} obj - particualr form
* @constructor
*/
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){
var $succesRegisterModal,
mailVal;
responseData = data;
self.unHighlightFields();
if(responseData.success){
if(DOMerrBox){
EXPO.common.removeClass(DOMerrBox, 'active');
}
if($(self.DOM).attr('id') == EXPO.common.opt.registerFormId){
$succesRegisterModal = $('#'+EXPO.common.opt.successRegisterId);
mailVal = $.trim($('#id_email',self.DOM).val());
$('.'+EXPO.common.opt.resendLetterClass,$succesRegisterModal).attr('data-email',mailVal);
$.fancybox.close(true);
$.fancybox('#'+EXPO.common.opt.successRegisterId);
}else{
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();
}
$waiter.hide();
};
self.unHighlightFields();
$waiter.show();
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 () {
/**
* $.fancybox bug fix, caused because fancybox is loading near body tag end
*/
$.fancybox.helpers.overlay.overlay = $('<div class="fancybox-overlay"></div>').appendTo('body');
/* Нестандартное оформление для поля 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("<span class='custom-"+ type +"' />").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
//$.fancybox('#pw-reg-complete');
});
/**
* very simple (probably in much need of improvement) Jquery plugin I've thrown together that will get you the value of an inline style property
*/
(function ($) {
$.fn.inlineStyle = function (prop) {
var styles = this.attr("style"),
value;
styles && styles.split(";").forEach(function (e) {
var style = e.split(":");
if ($.trim(style[0]) === prop) {
value = style[1];
}
});
return value;
};
}(jQuery));
/**
* current module general initialization
* @param {Object} options - options recieved from web page view
*/
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);
$waiter = $('#wait-ajax:not(.absolute)').css({'z-index': '8031'});
$('.'+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);
}
})
}
/**
* "http://" placeholder for social profiles form on user and company "edit profiles" pages
*/
for(var i = 0; i < self.opt.httpFormIds.length; i++){
var $instance = $('#'+self.opt.httpFormIds[i]);
if($instance.length){
$('input:text', $instance).on('focus', function () {
var $this = $(this),
placeholder = self.opt.socialInputMask;
if($.trim($this.val()) == ''){
$this.val(placeholder[0]);
}
});
$('input:text', $instance).on('keypress', function () {
var $this = $(this),
placeholder = self.opt.socialInputMask;
if($.trim($this.val()) == ''){
$this.val(placeholder[0]);
}
});
$('input:text', $instance).on('blur', function () {
var $this = $(this),
placeholder = self.opt.socialInputMask;
for(var i =0; i< placeholder.length; i++){
if($.trim($this.val()) == placeholder[i]){
$this.val('');
}
}
});
}
}
// seohide
/**
* setup SEOhide params
*/
$('.'+self.opt.seoLinksClass).each(function () {
var hash = $(this).attr('data-hash'),
url = $(this).attr('data-url');
EXPO.common.SEOhide.seoHrefs[hash] = url;
});
/**
* launch algorithm
*/
EXPO.common.SEOhide.decode(self.opt.dataKey);
/**
* resend a letter button controller
*/
$('.'+self.opt.resendLetterClass).on('click', function () {
var email = $(this).attr('data-email'),
url = self.opt.resendLetterUrl;
$waiter.show();
EXPO.common.getRequest({'email':email},url, function (data) {
$waiter.hide();
});
return false;
});
/**
* hide error icon on validated field when it is focused
*/
$('#'+self.opt.socialFormId).on('focus','.'+self.opt.requiredClass+'.'+self.opt.errorClass+' input:text',function () {
$(this).closest('.'+self.opt.errorClass).addClass('disable-inner');
});
$('#'+self.opt.socialFormId).on('blur','.'+self.opt.requiredClass+'.'+self.opt.errorClass+' input:text',function () {
$(this).closest('.'+self.opt.errorClass).removeClass('disable-inner');
});
});
//$(window).load(function () {
// $waiter.detach().appendTo('body');
//});
};
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';
}
};
/**
* implementation of well known algorithm SEOhie.js (http://goo.gl/MyuQl9)
* hides external links or text from search engines
* depends on Base64.js (http://goo.gl/iblGuK)
* @public
* @type {{seoContent: {}, seoHrefs: {}, decode: Function}}
* @prop {object} seoContent - hashes to find proper content to hide
* @prop {object} seoHrefs - hashes to find proper links to hide on page
* @method decode - decode bas64-code to html
*/
that.SEOhide = {
seoContent:{},
seoHrefs:{},
/**
* @param dataKey - key to find hashes
*/
decode: function (dataKey) {
var $elements = $('['+dataKey+']');
for(var i = 0, count = $elements.length; i < count; i++) {
var $element = $elements.eq(i);
var key = $element.attr("data-hash");
switch($element.data("type")) {
case "href":
$element.attr("href", Base64.decode(this.seoHrefs[key]));
break;
case "content":
$element.replaceWith(Base64.decode(this.seoContent[key]));
break;
}
}
}
};
/**
* format raw text (for example textarea input data), replaces newline by tag <br>
* @param {String} str string value to process
* @param {Boolean} is_xhtml if true than use xhtml notation for tag <br>
* @returns {string} formateed string
*/
that.nl2br = function (str, is_xhtml) {
var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br ' + '/>' : '<br>'; // Adjust comment to avoid issue on phpjs.org display
return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + breakTag + '$2');
};
return that;
}());
}