UNPKG

withfront

Version:

Tools for frontend development especially with Bootstrap 3.x and jQuery 3.x also FontAwesome, jsCookie and more

1,339 lines (1,196 loc) 66 kB
/* * * * * * * * * * * * * * Start * * Window on buffer onload * * * * * * * * * * * * */ // Message to be displayed on unload // var message = $('#jtrnslt #leavemess').text(), submitting = false; // // On Form submition set submitting to true for not fire onbeforeunload // $(document).on("submit", "form", function(event){ // submitting = true; // }); // // Window onbeforeunload fired when leave page but not if it a form submition or element with .noBeforeUnload class // window.onbeforeunload = function (e) { // e = e || window.event; // // Determine if you want to allow unload // /* some synchronous operation here*/ // if (!submitting && !$(e.target.activeElement).hasClass('noBeforeUnload')) { // // IE BUG: throws unspecified error on "cancel" // // so we temporarily mask all Javascript errors // window.onerror = function (msg, url, linenumber) { // return -1 < msg.toLowerCase().indexOf('unspecified error'); // }; // // After return the (blocking) confirmation window is shown // // after which we remove Javascript error handler // window.setTimeout(function () { // window.onerror = function () { // return false; // } // }, 100); // // -- IE BUG // // // default message if missed // if (message.length == 0) { // message = 'Are you sure you want leave this page without save? Sei sicuro di volere uscire senza salvare?'; // } // // // IE expects the confirmation string in the // // `returnValue` property of event object // if (e) { // e.returnValue = message; // } // // Other browsers expect it returned as a string // return message; // } // }; /* * * * * * * * * * * * * * END * * Window on buffer onload * * * * * * * * * * * * */ /** * Default conf enable/disable withPlugins functions * * @object {{ * debug: boolean, * wAppearBottomButton: boolean, * go2top: boolean * }} */ var withOptions = { debug: false, // enable/disable Debug mode wAppearBottomButton: false, // enable/disable widget/w-appear_btn.js -Bottom wAppearTopButton: false, // enable/disable widget/w-appear_btn.js -Top go2top: true, // enable/disable widget/w-go2top.js htmlNicescroll: false, whatsappWeb: true, // replace WhatsApp mobile with Desktop on Desktop }; if (typeof wOptions != 'undefined') { var withOptions = $.extend(withOptions, wOptions); } /** * Debug function for console.info() messages only if debug mode is enabled * so you don't need to worry about your debug message when in production * * @param text */ function clog(text){ if (withOptions.debug) { console.info(text); } } /** * wCookies - Cookies() `js-cookie` (https://github.com/js-cookie/js-cookie) * .get(name); * .set(name, value, attributes); * .remove(name, attributes); * .getJSON([name]); */ if(typeof Cookies != 'undefined') { clog('cookie are baked'); wCookies = function() { return { get: function(name) { clog('cookie-get(name):' + name); return Cookies.get(name); }, set: function(name, value, attributes) { // var defaults = { // //secure: true, // we yet on secure from server // //expires: 365, // no only one session // //path: '/', domain: '', // yet default // }; // var attributes = $.extend(defaults, options); clog('cookie-set(name, value, attributes):' + name + ', ' + value + ', ' + attributes); Cookies.set(name, value, attributes); }, remove: function(name, attributes) { clog('cookie-remove(name, attributes):' + name + ', ' + attributes); Cookies.remove(name, attributes); }, getJSON: function (name) { Cookies.getJSON(name); }, getJSON: function () { // get all in JSON return Cookies.getJSON(); } }; }; } /** * withAlert() [>= v1.4.5] * gdivMessage() [< v1.4.5] * * @dependencies [css: bootstrap(.alert), withstyle(.withAlert), jquery] * * @param string message * @param string type * @param object options {autohide:true, hidetime:4000} */ (function ($) { /** * @deprecated use withAlert() instead * * @param string message * @param string type * @param object options */ $.fn.gdivMessage = function (message, type, options) { var defaults = {autohide: true, hidetime: 6000}; var opts = $.extend(defaults, options); var zindex = 5001, top = 70, alert_count = 1; if (!message) { message = 'Errore inaspettato. Scusate per il disagio. (Unexpected Error)'; } if (!type) { type = 'warning'; } _alert_count = parseInt($(".withAlert").length); if (_alert_count > 0) { alert_count = _alert_count; } zindex = alert_count + 5001; top = alert_count * top; if (top > 100) { top = 100 + (alert_count * 3); if (top > 150) { top = 150; } } // qui creiamo il codice del alert var element = '<div class="withAlert alert alert-' + type + ' alert-dismissible" style="z-index: ' + zindex + '; top: ' + top + 'px;"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button><span class="message">' + message + '</span><div class="clearfix"></div></div>'; var eobj = $(element).clone(); $(eobj).appendTo("body"); $(eobj).addClass('in'); if (opts.autohide) { setTimeout(function () { $(eobj).hide('slow', function () { $(this).remove(); }); }, opts.hidetime); } }; })(jQuery); $("body").on('click', ".withAlert .close", function () { $(this).parent().hide('slow', function () { $(this).remove(); }); }); /* * * * ----- gDiv Message ----- * * */ /** * withAlert() - the new gdivMessage() * no $.fn jQuery function so you can call it without an html object * and new beautiful name (bootstrap4 also) * * @param string message * @param string type warning|success|danger|primary|secondary|info * @param object options {autohide: true/false, hidetime: 6000, placement: top|bottom} */ function withAlert(message, type, options) { var defaults = {autohide: true, hidetime: 6000, placement: 'top'}; var opts = $.extend(defaults, options); var zindex = 5001, top = 70, alert_count = 1, _alert_count = 0; if (!message) { message = 'Errore inaspettato. Scusate per il disagio. (Unexpected Error)'; } if (!type) { type = 'warning'; } _alert_count = parseInt($(".withAlert").length); if (_alert_count > 0) { alert_count = _alert_count; } zindex = alert_count + 5001; top = alert_count * top; if (top > 100) { top = 100 + (alert_count * 3); if (top > 150) { top = 150; } } // here we create the bootstrap 4 alert code var element = '<div class="withAlert alert alert-' + type + ' alert-dismissible fade show" style="z-index: ' + zindex + '; '+ opts.placement +': ' + top + 'px;"><button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button><span class="message">' + message + '</span><div class="clearfix"></div></div>'; var eobj = $(element).clone(); $(eobj).appendTo("body"); $(eobj).addClass('in'); if (opts.autohide) { setTimeout(function () { $(eobj).hide('slow', function () { $(this).remove(); }); }, opts.hidetime); } } $(".loader-wrapper-close").show().click(function () { $(".loader:not(.demo-loader)").fadeOut(200); $(".loader-wrapper:not(.demo-loader)").delay(100).fadeOut(400); }); /* jQuery plugins and other thing that need to be run after the document is load */ $(document).ready(function () { // this is for loader if ($(".loader-wrapper").length > 0) { $('#mainMenu a:not([target="_blank"]):not([href^="#"]), a.animation-link').on("click", function () { // Grab the link's href var href = this.href; $(".loader").fadeIn(300); // Slide up the content you want to slide up $(".loader-wrapper").fadeIn(function () { // Slide is finished, navigate location.href = href; }); // Prevent the default action of the link return false; }); $(window).on('load', function () { $(".loader:not(.demo-loader)").fadeOut(200); $(".loader-wrapper:not(.demo-loader)").delay(100).fadeOut(400); }); } }); /* jQuery plugins and other thing that need to be run after the document is load */ $(document).ready(function () { /** * withHoneyPot Spam Checker * * Example: * CSS: ._the_email_confirm_group { display: none !important; } * * HTML: <div class="_the_email_confirm_group"> <div class="form-group"> <label class="upper" for="name">Email confirm</label> <input type="text" class="_the_email_confirm_" name="_the_email_confirm_" value="confirmed" /> </div> </div> * HTML END; * * PHP: $captcha_error = false; $maybe_js_error = false; if (isset($_POST['_the_email_confirm_']) && strlen($_POST['_the_email_confirm_']) > 0) { if ($_POST['_the_email_confirm_'] == 'confirmed') { $maybe_js_error = true; } else { $captcha_error = true; $errors[] = 'Codice di sicurezza "CAPTCHA" non valido'; } } if ( ! $captcha_error && ! $errors) { if ($maybe_js_error) { // if error maybe spam $email_to = 'buonemailrn@gmail.com'; } else { // send to owner $email_to = $to; } } * PHP END; */ $("._the_email_confirm_").attr('value', ''); // detect if the width of screen is bootstrap xs, sm, md, lg var isXs = window.matchMedia("(max-width: 768px)"), isSm = window.matchMedia("(min-width: 768px) and (max-width: 991px)"), isMd = window.matchMedia("(min-width: 992px) and (max-width: 1199px)"), isLg = window.matchMedia("(min-width: 1200px)"), //Bootstrap4 style is4sm = window.matchMedia("(min-width: 576px)"), is4md = window.matchMedia("(min-width: 768px)"), is4lg = window.matchMedia("(min-width: 992px)"), is4xl = window.matchMedia("(min-width: 1200px)"); (function (a) { (jQuery.browser = jQuery.browser || {}).mobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4)) })(navigator.userAgent || navigator.vendor || window.opera); /*============================== Is mobile ==============================*/ // var isMobile = { // Android: function() { // return navigator.userAgent.match(/Android/i); // }, // BlackBerry: function() { // return navigator.userAgent.match(/BlackBerry/i); // }, // iOS: function() { // return navigator.userAgent.match(/iPhone|iPad|iPod/i); // }, // Opera: function() { // return navigator.userAgent.match(/Opera Mini/i); // }, // Windows: function() { // return navigator.userAgent.match(/IEMobile/i); // }, // any: function() { // return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); // } // } /** * Boxes AutoHeight by default only for desktop devices * * @dependencies [w-breakpoints] * @param columns 'selector for the element to make equal' * @param direction [optional] '<', '>', '=' * * Add class to father element * `.withEqualHeight` = for small device and higher (not for xs) * `.withEqualHeightInverse` = for the smallest element instead of tallest * `.withEqualHeightLike` = for equal height element like the element with .wehl class * `....All` by adding All at the end ex: `.withEqualHeightAll` = for extra small device and higher * * And to all child add class `.weh` and `.wehl` if you wont a height like specific element * * If you want additional height to all elements (ex: for add a button with absolute position etc.) * Add `data-weh-add="50"` to children `.weh` elements (add 50px to all) * * @todo: css relative class for IDE support * @todo: i think the best way for data-weh-add is in father element and not in all children */ function withEqualHeight(columns, direction) { var columnHeight= 0, add = parseInt(columns.first().attr('data-weh-add')), i=0; if (isNaN(add)) { // check for data-weh-add in parent add = parseInt(columns.parents('[class*="withEqualHeight"]').attr('data-weh-add')) if (isNaN(add)) { add = 0; } } if (typeof direction == 'undefined') { direction = '>'; } if (direction == '=') { var likeColumn = columns.parents('.withEqualHeightLike').find('.wehl').first(); likeColumn.css('height', 'auto'); columnHeight = likeColumn.height(); } else { columns.each( function (i) { $(this).css('height', 'auto'); var currentHeight = $(this).height(); if (direction == '>') { if (currentHeight > columnHeight) { columnHeight = currentHeight; } } else if (direction == '<') { if (i == 0) { columnHeight = currentHeight; } if (currentHeight <= columnHeight) { columnHeight = currentHeight; } } i++; } ); } columns.height(columnHeight+ add); } $(window).on('load resize', function () { // .withEqualHeight > .weh for elements, non in `xs` media screen if (!isXs.matches) { $('.withEqualHeight').each(function () { withEqualHeight($(this).find('.weh')); }); // @todo: totest $('.withEqualHeightInverse').each(function () { withEqualHeight($(this).find('.weh'), '<'); }); $('.withEqualHeightLike').each(function () { withEqualHeight($(this).find('.weh'), '='); // search for .wehl element and make all other equal to it }); } // .withEqualHeightAll > .weh for all elements $('.withEqualHeightAll').each(function () { withEqualHeight($(this).find('.weh')); }); // @todo: totest $('.withEqualHeightInverseAll').each(function () { withEqualHeight($(this).find('.weh'), '<'); }); $('.withEqualHeightLikeAll').each(function () { withEqualHeight($(this).find('.weh'), '='); // search for .wehl element and make all other equal to it }); }); /** w-filter * Filter items on button click or select change with data-filter=".selector" */ $(".w-filters").each(function(){ var $grid = $(this); $grid.on('click change', '.w-filter', function() { var filterValue = ''; if($(this).is('select')) { filterValue = $(this).val(); } else if ($(this).is('radio')) { // @todo // console.info('radio'); // console.info($(this).val()); } else { // remove and add active state $grid.find('.w-filter').removeClass('active'); $(this).addClass('active'); // filter items filterValue = $(this).attr('data-filter'); } // hide all elements $(".w-item", $grid).hide(); // show filtered $(".w-item"+filterValue, $grid).show(); }); }); /** * Add event to `.child_num_input` for clone `#child_ageClone` on change * to create as many inputs as is the number of children * * @dependencies [w-alert] * * @param form The form on that it work `.children_age_form` * @param childNum The number of children, for create it age inputs * * <form>.children_age_form * <input>.child_num_input * <div>#child_ageClone * * --- and --- * * <form class="children_age_form"> * <input type="number" class="form-control child_num_input" min="0" max="5" name="num_children"> * * if is select input add class .input_select after .child_num_input * * --- and --- * * <div class="col-sm-2 pull-right display-none" id="child_ageClone" data-attr-name="if_you_want_change_the_attr_name_dynamically"> * <div class="form-group"> * <input type="number" placeholder="0" class="form-control" name="age_children[]" value="0" max="17" min="0" disabled/> * * <label>Children <span class="jq_child_num">1</span></label> * </div> * </div> * * --- and --- * * $php * $children_number = $_POST['num_children']); // 3 * $children_age = implode(', ', $_POST['age_children']); // 3, 6, 7 * $endphp * * max children: default 5 (configurable by max attribute) * @todo: keep values of yet inserted children ages (w-cookie) * @type {any} */ function addAges(form, childNum) { $("[id^='child_age_']", form).remove(); // first remove all childNum = parseInt(childNum); // if counter are equal 0 - do nothing if (childNum == 0) { return false; } // set {max_children} var max_children = parseInt($('.child_num_input', form).attr('max')); if (typeof max_children == 'undefined') { max_children = 5; } // over {max_children} are invalid if (childNum > max_children) { if (typeof withAlert == 'function') { withAlert('No more then ' + max_children + ' childs / Non più di ' + max_children + ' bambini', 'warning', {hidetime: 7000}); } else { alert('No more then ' + max_children + ' childs / Non più di ' + max_children + ' bambini', 'warning'); } $('.child_num_input', form).val(max_children); childNum = max_children; } for (var _cN = 1; _cN <= childNum; _cN++) { if (_cN > max_children) { $('.child_num_input', form).val(max_children); return false; } var childClone = $('#child_ageClone', form).clone(); // change params childClone.attr('id', 'child_age_' + _cN); childClone.find('.jq_child_num').text(_cN); // input childClone.find('input') .prop("disabled", false) .removeProp('disabled') .attr('data-binded', childClone.find('input').attr('data-binded') + _cN + ' input'); // `data-attr-name` you can also change other attributes ex: .attr('placeholder', 'Eta Bambino_' + _cN) if (typeof childClone.attr('data-attr-name') != 'undefined' && childClone.attr('data-attr-name').length) { childClone.find('input').attr('name', childClone.attr('data-attr-name') + _cN); } // attach and show $('#child_ageClone', form).after(childClone); childClone.show(); } } $(".children_age_form").each(function () { var form = $(this); clog('.children_age_form: Enabled'); // add event trigger for form form.on('keyup change', '.child_num_input', function () { clog('.children_age_form: Form input change'); // loop and add age inputs if ($(this).attr('type') == 'checkbox' || $(this).attr('type') == 'radio' || $(this).hasClass('checkbox_input')) { clog('.children_age_form: Input checkbox or radio, value= '+$('.child_num_input:checked', form).val()); addAges(form, $('.child_num_input:checked', form).val()); } else if ($(this).hasClass('select_input')) { clog('.children_age_form: Input .select_input, value= '+$('.child_num_input:selected', form).val()); addAges(form, $('.child_num_input:selected', form).val()); } else { clog('.children_age_form: Input value= '+$('.child_num_input', form).val()); addAges(form, $('.child_num_input', form).val()); } }); // init childNum counter $(function(){ // we need to wait for wCookie set of value in some case setTimeout(function() { var _cni = $('.child_num_input', form); if (_cni.attr('type') == 'checkbox' || _cni.attr('type') == 'radio') { addAges(form, $('.child_num_input:checked', form).val()); } else if (_cni.hasClass('select_input')) { addAges(form, $('.child_num_input:selected', form).val()); } else { addAges(form, $('.child_num_input', form).val()); } }, 3000); }); }); /* notInclude('js/form/w-ajaxsave.js') */ /* notInclude('js/web/w-analytics.js') */ /** * Ajax Form * ContactsController()->ajaxsend() * * .ajaxsend * data-ga-send-pageview="/email-form-contatti" * data-gaq-track-pageview="/email-form-contatti" // for use the old version of Google Analytics * * * method: same as form method="POST" * url: same as form action="" * data: all form fields with jQuery.serialize() * dataType: json * * success expect: { * success: true/false, * message: 'string', // for show an alert with this message * errors: array/object, // with index like the name of input that have error * string_error: 'all errors in one string', // for show in <div class="errors"></div> * } * * @dependencies [w-alert(optional), font-awesome, jquery] **/ $(".ajaxsend").submit(function (e) { e.preventDefault(); var form = $(this); // loader var submit_btn = $(this).find('[type=submit]'); var submit_btn_text = submit_btn.text(); submit_btn.html(submit_btn_text + ' &nbsp; <i class="fa fa-spinner fa-pulse"></i>').prop('disabled', true); // errors $('input, select, textarea').parent().removeClass('has-error').find('.help-block').remove(); form.find('.errors').hide(); $.ajax({ method: form.attr('method'), url: form.attr('action'), data: form.serialize(), dataType: "json", success: function (json) { // loader submit_btn.text(submit_btn_text).prop('disabled', false); if (json.success) { // Google Analytics track if (typeof ga !== "undefined" && form.data('gaSendPageview') != 'off') { var gaSend = (typeof form.data('gaSendPageview') != 'undefined') ? form.data('gaSendPageview') : '/email-form-contatti'; ga('send', 'pageview', gaSend); clog('ga send pageview: ' + gaSend); } // #GA4 if (typeof gtag !== "undefined" && form.data('ga4SendEvent') != 'off') { var ga4SendEvent = (typeof form.data('ga4SendEvent') != 'undefined') ? form.data('ga4SendEvent') : 'form_contatti'; gtag('event', ga4SendEvent, { value: 20, currency: 'EUR' }); clog('ga4 send pageview: ' + ga4SendEvent); } // Facebook track (custom of this installation) clog('check fbq'); if (typeof fbq !== "undefined" && form.data('fbqLead') != 'off') { var fbqLead = (typeof form.data('fbqLead') != 'undefined') ? form.data('fbqLead') : 'Lead'; fbq('track', fbqLead); clog('fbq track: '+ fbqLead); } // Old Google analytics _gaq _trackPageview // if (typeof _gaq !== "undefined" && typeof form.data('gaqTrackPageview') != 'undefined') { // _gaq.push(['_trackPageview', form.data('gaqTrackPageview')]); // } if (json.message.length) { if (typeof withAlert == 'function') { withAlert(json.message, 'success', { hidetime: 15000 }); } else { alert(json.message); } } form.html('<h3>' + json.message + '</h3><h1 class="text-center"><i class="fa fa-check fa-5x text-success"></i></h1>', 1500); $('.on-target').css('background-color', '#00e095'); // setTimeout(function(){ // $('.on-target').css('background-color', 'transparent'); // }, 8000); } else { if (typeof json.message == 'undefined' || json.message.length == 0) { json.message = 'Errori nella form, correggi e riprova! Form errors, correct and try again!'; } if (typeof withAlert == 'function') { withAlert(json.message, 'danger'); } else { alert(json.message); } for (err in json.errors) { $(form).find('[name="'+err+'"]').parent() .after('<span class="help-block alert alert-danger">' + json.errors[err] + '</span>') .addClass('has-error'); } form.find('.errors').show(); form.find('.errors').html('<h4>' + json.message + '</h4><p>' + json.string_errors + '</p>', 1500); } }, error: function (e) { submit_btn.text(submit_btn_text).prop('disabled', false); if (typeof withAlert == 'function') { withAlert('Unexpected error! Errore inaspettato! :( ', 'danger'); } else { alert('Unexpected error! Errore inaspettato! :( '); } $('.errors', form).show(); $('.errors', form).html('<h4>Unexpected error! Errore inaspettato! :( </h4>', 1500); } }); return false; }); /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** # # # # # # # hash-navigation # for bootstrap tabs # # # # # # # # # ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ var hash = window.location.hash; if (hash.length > 0 && $('.hash-navigation').length > 0) { $('a[href=' + hash + ']').tab('show'); } // # look for changes in navigation and add it to url $('.hash-navigation a[data-toggle="tab"]').on('shown.bs.tab', function (e) { return location.hash = $(e.target).attr('href').substr(1); }); /** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** # # # # # # # # # # # hash-navigation # END # # # # # # # # # # # # # ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** **/ /** * #jQuery.plugin - bootstrap date picker * * @dependencies [uxsolution/bootstrap-datepicker] * * <div class="period"> + (data-date-start-date="default:today(0d)" data-date-end-date="default:none") and all other options https://bootstrap-datepicker.readthedocs.io/en/stable/options.html * <div class="form-group"> * <input type="text" name="checkin" id="checkin" class="form-control checkin range"> * </div> * <div class="form-group"> * <input type="text" name="checkout" id="checkout" class="form-control checkout range"> * </div> * </div> */ if ($().datepicker) { var bsdp_lang_code = $("#bsdp_lang_code").attr('data-lang'); if (typeof bsdp_lang_code == 'undefined' || bsdp_lang_code.length == 0) { bsdp_lang_code = $("html").attr('lang'); } if (typeof bsdp_lang_code == 'undefined' || bsdp_lang_code.length == 0 || bsdp_lang_code == 'en') { bsdp_lang_code = 'en-GB'; } // contact page datepicker $('.period').each(function () { var period = $(this); $("input.range", period).attr('autocomplete', 'off'); if (period.data('dateStartDate')) { startDate = period.data('dateStartDate'); } else { var startDate = '0d'; } period.datepicker({ startDate: startDate, format: 'dd/mm/yyyy', inputs: $('input.range', period), todayHighlight: true, todayBtn: 'linked', daysOfWeekHighlighted: "0", zIndexOffset: 9999, orientation: 'bottom', autoclose: true, language: bsdp_lang_code }); // focus on checkout when checkin is set var checkin = period.find('input.checkin'), checkout = period.find('input.checkout'); checkin.datepicker() .on('changeDate', function (e) { $("input.checkout", period).focus(); }); // set checkout to next day if dates are the same checkout.datepicker().on('changeDate', function (e) { var checkin_date = checkin.datepicker('getUTCDate').getTime(), checkout_date = checkout.datepicker('getUTCDate').getTime(); if (checkin_date == checkout_date) { var next_day = new Date(checkout_date).getTime() + 86400000; checkout.datepicker('update', new Date(next_day)); } }); // checkout.datepicker() // you can continue to focus input of user // .on('changeDate', function (e) { // $("..next input selector..", period.parent()).focus(); // }); }); } // END - #jQuery.bootstrap date picker // #jQuery.plugin - bootstrap tooltips if ($().tooltip) { $('[data-toggle=tooltip]').tooltip(); } // END - #jQuery.tooltip // #jQuery.plugin - selectize for list options if ($().selectize) { $('.selectize').selectize(); } // END - #jQuery.selectize // #jQuery.plugin - bootstrap switch for radio button if ($().bootstrapSwitch) { $(".bootstrapSwitch").bootstrapSwitch(); } // END - #jQuery.bootstrapSwitch /** * # jQuery.plugin - Nicescroll * https://github.com/inuyaksa/jquery.nicescroll * * @dependencies [nicescroll, w-core] * * with data-api for set: * wns-background, wns-cursorcolor, wns-cursorwidth, wns-cursorborder, wns-railalign, wns-cursorborderradius, wns-boxzoom, wns-horizontalenabeld, wns-autohidemode */ if ($().niceScroll) { if (typeof withOptions.htmlNicescroll != 'undefined' && withOptions.htmlNicescroll) { $("html").niceScroll({ background: $("html").data('wnsBackground') || "#e2e2e2", cursoropacitymin: 1, cursorcolor: $("html").data('wnsCursorcolor') || "#141414", cursoropacitymax: 0.6, cursorwidth: $("html").data('wnsCursorwidth') || 5, cursorborder: $("html").data('wnsCursorborder') || '0px solid #fff', railalign: $("html").data('wnsRailalign') || "right", railpadding: {top: 0, right: 0, left: 0, bottom: 0}, cursorborderradius: $("html").data('wnsCursorborderradius') || "0px", boxzoom: $("html").data('wnsBoxzoom') || false, horizrailenabled: $("html").data('wnsHorizrailenabled') || false, autohidemode: $("html").data('wnsAutohidemode') || false }); // fix horizontal @todo: when? $('html').addClass('no-overflow-y'); } $(".withNicescroll, .w-nicescroll").each(function(){ var breakpoint = true; if ($(this).data('wnsBreakpoint') == 'is4md') { breakpoint = is4md.matches; } if (breakpoint) { var wns = $(this), wncOptions = { background: wns.data('wnsBackground') || "#e2e2e2", cursoropacitymin: 1, cursorcolor: wns.data('wnsCursorcolor') || "#141414", cursoropacitymax: 0.6, cursorwidth: wns.data('wnsCursorwidth') || 5, cursorborder: wns.data('wnsCursorborder') || '0px solid #fff', railalign: wns.data('wnsRailalign') || "right", railpadding: {top: 0, right: 0, left: 0, bottom: 0}, cursorborderradius: wns.data('wnsCursorborderradius') || "0px", boxzoom: wns.data('wnsBoxzoom') || false, horizrailenabled: wns.data('wnsHorizrailenabled') || false, autohidemode: wns.data('wnsAutohidemode') || false } wns.niceScroll(wncOptions); } }); } // END - jQuery.nicescroll /** * Replace mobile URL of WhatsApp with Desktop * The mobile first strategy is used cause most people decide to not show WhatsApp on Desktop but only on mobile where it is very useful * * @dependencies [ core/w-ismobile.js ] */ if(withOptions.whatsappWeb && !jQuery.browser.mobile && $(".whatsapp-weburl").length > 0){ clog('WhatsApp Enabled and Present'); $(".whatsapp-weburl").each(function(){ clog($(this)); clog($(this).attr('href')); var mobile_wa = $(this).attr('href').replace('?text=', '&text='); mobile_wa = mobile_wa.replace('https://wa.me/', 'https://web.whatsapp.com/send?phone=+') clog(mobile_wa); $(this).attr('href', mobile_wa); }); } /** * Add target highlight to something * * data-target [-] CSS Selector for select the element on which apply * data-auto-close [8000] Bool or the ms for close * data-taregt-class [on-target] The class to add (default have CSS animation but it must be on the #anchor element also) */ $("body").on('click', '.targetLink, .w-target', function () { var elem = $(this).data('target'); var autoClose = (typeof $(this).data('autoClose') != 'undefined') ? $(this).data('autoClose') : 8000; var targetClass = (typeof $(this).data('targetClass') != 'undefined') ? $(this).data('targetClass') : 'on-target'; $(elem).addClass(targetClass); if (autoClose) { if (autoClose === true) { autoClose = 8000; } setTimeout(function () { $(elem).removeClass(targetClass); }, autoClose); } }); /** * Animate scroll of #hash anchor and put the window to right place with topOffset * * data-keep-hash [false] If #hash anchor is needed in url set true, otherwise u will not see the #hash in url * data-top-offset [10] The NEGATIVE offset from top (for not cover things with navbar or other things) * data-animation [1000] The duration of scroll animation * */ $("body").on('click', ".w-scroll", function (e) { if (this.hash !== "" && $(this.hash).length) { e.preventDefault(); // Store hash var hash = this.hash, keep_hash = (typeof $(this).data('keepHash') == "undeifned") ? false : $(this).data('keepHash'), topOffset = $(this).data('topOffset'), animation = (typeof $(this).data('animation') == "undefined") ? 1000 : parseInt($(this).data('animation')); // calc topOffset by passed type of data, int or selector if (typeof topOffset == "undefined") { topOffset = 10; // default } else { _topOffset = parseInt(topOffset); // if it not numeric, we assume that it an element from which take height if (isNaN(_topOffset)) { if ($(topOffset).length) { topOffset = $(topOffset).height(); } else { topOffset = 10; // default } } else { topOffset = _topOffset; } } $("html, body").animate({ scrollTop: $(hash).offset().top - topOffset }, animation, function () { // Add hash (#) to URL when done scrolling (default click behavior) if (keep_hash) { window.location.hash = hash; } }); } else { if(this.hash != "") { console.info('Error: Define element with id="'+this.hash+'"'); } else { console.info('Error: You must add an anchor href="#some_id" to your trigger element with class .w-scroll or it won\'t work'); } } }); // bootstrap wide modal - adjust height to fit entire page $(".modalWide").on("show.bs.modal", function() { var height = $(window).height() - 200; $(this).find(".modal-body").css("max-height", height); }); // END - bootstrap wide modal /** * Animate the bottom appear button .wabb .left .right * * <a type="button" href="javascript:;" class="wabb right btn btn-primary" data-bottom="60" data-delay="1440"> * Bottom Button <i class="fa fa-check"></i> * </a> * * data-bottom: the position from bottom(60 default) * data-right: with .right the position from bottom(CSS 105px default, 75px on mobile) * data-left: with .left the position from bottom(CSS 105px default, 75px on mobile) * data-delay: after how many ms the button appear(1440 default) * **/ var wAppearBottomButton = function () { return { init: function () { var wabb = $('.wabb'), bottom_pos = wabb.data('bottom') || 20, right_pos = parseInt(wabb.data('right')), left_pos = parseInt(wabb.data('left')), delay = wabb.data('delay') || 1440; if(!wabb.hasClass('right') && !wabb.hasClass('left')){ wabb.addClass('right'); } if (right_pos > 0) { wabb.css('right', right_pos+'px'); } if (left_pos > 0) { wabb.css('left', left_pos+'px'); } setTimeout(function () { wabb.stop().animate({bottom: bottom_pos+'px'}, 800); }, delay); if (withOptions.debug) { console.info('wAppearBottomButton() enabled'); } } }; }(); if (withOptions.wAppearBottomButton) { wAppearBottomButton.init(); // with Appear Bottom Button {css: .wabb} } /** * Animate the top appear button .watb .left .right * * <a type="button" href="javascript:;" class="watb right btn btn-primary" data-top="60" data-delay="1440"> * Top Button <i class="fa fa-check"></i> * </a> * * data-top: the position from top(20 default) * data-right: with .right the position from bottom(CSS 105px default, 75px on mobile) * data-left: with .left the position from bottom(CSS 105px default, 75px on mobile) * data-delay: after how many ms the button appear(1440 default) * **/ var wAppearTopButton = function () { return { init: function () { var watb = $('.watb'), top_pos = parseInt(watb.data('top')) || 20, right_pos = parseInt(watb.data('right')), left_pos = parseInt(watb.data('left')), delay = watb.data('delay') || 1440; if(!watb.hasClass('right') && !watb.hasClass('left')){ watb.addClass('right'); } if (right_pos > 0) { watb.css('right', right_pos+'px'); } if (left_pos > 0) { watb.css('left', left_pos+'px'); } setTimeout(function () { watb.stop().animate({top: top_pos+'px'}, 800); }, delay); if (withOptions.debug) { console.info('wAppearTopButton() enabled'); } } }; }(); if (withOptions.wAppearTopButton) { wAppearTopButton.init(); // with Appear Bottom Button {css: .watb} } /** * START: Layout Go2Top * css: .go2top * dependencies: bootstrap, font-awesome * * <div class="go2top hidden-xs text-center"> * <i class="fa fa-chevron-circle-up"></i> * <p class="hidden-sm">Torna su</p> * </div> */ var LayoutGo2Top = function () { var handle = function () { var currentWindowPosition = $(window).scrollTop(); // current vertical position if (currentWindowPosition > 300) { $(".go2top").show(); } else { $(".go2top").hide(); } }; return { //main function to initiate the module init: function () { handle(); // call headerFix() when the page was loaded if (navigator.userAgent.match(/iPhone|iPad|iPod/i)) { $(window).bind("touchend touchcancel touchleave", function (e) { handle(); }); } else { $(window).scroll(function () { handle(); }); } $(".go2top").on('click', function (e) { e.preventDefault(); $("html, body").animate({ scrollTop: 0 }, 600); }); } }; }(); if (withOptions.go2top) { LayoutGo2Top.init(); // go2top button {css: .go2top} } $(".w-sliding-panel").each(function () { var slidingPanel = $(this), slidingBtn = $('.w-sliding-btn[data-target="#'+$(this).attr('id')+'"]'), noCloseBtn = slidingBtn.data('noCloseBtn'); // Get the calculated left position var slidingPanel_left = slidingPanel.offset().left; var slidingPanel_width = $(document).width(); // Set the left to its calculated position slidingPanel.css({left:slidingPanel_left, width:slidingPanel_width}); // on click slide slidingBtn.on('click', function () { showGestPanel(); }); slidingPanel.on('click', '.close-panel', function () { hideGestPanel(); }); // on resize $(window).on('resize', function () { // get new width for hide slidingPanel_width = $(document).width(); hideGestPanel(); // hide panel for resize it and change position // Get the calculated left position slidingPanel_left = slidingPanel.offset().left; // Set the left to its calculated position slidingPanel.css({left:slidingPanel_left, width:slidingPanel_width}); }); function showGestPanel(){ slidingPanel.animate({"left":"0px"}); console.info(noCloseBtn) if (!noCloseBtn) { console.info('hide') slidingBtn.animate({"left":"-999px"}); } } function hideGestPanel(){ slidingPanel.animate({"left":'-'+slidingPanel_width+'px'}); if (!noCloseBtn) { slidingBtn.animate({"left": "0"}); } } // close on document click $(document).mouseup(function () { hideGestPanel(); }); }); // no close on himself click $(".w-sliding-panel").mouseup(function () { return false; }); // #jQuery.plugin - raty for a star rating view if ($().raty) { /** * Raty - https://github.com/wbotelhos/raty * with data API initialization from https://github.com/wbotelhos/raty/pull/168 * get only the star type or set my prefered icon type and all others from data-api: * <span class="getraty" data-score="5" data-star-on="fa fa-star" data-star-off="" data-read-only="true"></span> * */ $('.getraty').each(function () { // startype = i var startype = $(this).data('startype'); if (typeof startype == 'undefined' || startype.length == 0) startype = 'i'; // readonly = true var readonly = $(this).data('readonly'); if (typeof readonly == 'undefined' || readonly.length == 0) readonly = true; // score = 5 var score = $(this).data('score'); if (typeof score == 'undefined' || score.length == 0) score = 5; $(this).raty({starType: startype, readOnly: readonly, score: score}); }); } // END - #jQuery.raty /** * withBox * * div.withBox[.collapsable] * > div.showhideBox * > > div.shSwitch * > div.shBox * * ex: * <div class="withBox collapsable"> * <h2 class="showhideBox text-underline"> * Switcher * * <span class="pull-right"> * <i class="glyphicon glyphicon-chevron-right shSwitch"></i> * <i class="glyphicon glyphicon-chevron-down shSwitch display-none"></i> * </span> * </h2> * * <div class="shBox display-none"> * Content ... * </div> * </div> * * * #showhide https://gist.github.com/arturmamedov/2bdfc3f69828ac37a7a1 */ $(".withBox").on('click', ".showhideBox", function () { var thisBox = $(this), parent = false; while (parent == false) { thisBox = thisBox.parent(); if (thisBox.hasClass('withBox')) { parent = true; } } $(".shBox", thisBox).toggle(200); $(".shSwitch", thisBox).toggle(1, function () { if ($(this).hasClass('set')) $(this).removeClass('set'); else $(this).addClass('set'); }); }); // no close on himself click $(".withBox.collapsable").mouseup(function () { return false; }); // close on document click $(document).mouseup(function () { $(".shBox", $(".withBox.collapsable")).slideUp(); var shSwitch = $(".shSwitch.set", $(".withBox.collapsable")); shSwitch.toggle(1, function () { $(this).removeClass('set'); }); }); /** * Set values of inputs or elements from cookie * * @param _this HTML input element with data-name="" or name="" that correspond to cookie name, data-cookie-type="val,select,radio,html,text" */ function setFromCookie(_this){ if (typeof wCookies == 'undefined') { return; } var selector = _this.data('binded'), type = _this.data('cookie-type');; // get name from name="" or data-name="" var name = _this.attr('name'); if(typeof name == 'undefined') { name = _this.data('name'); } // get value from cookie var value = wCookies().get(name); if(typeof value == 'undefined' || value == '') { clog('setFromCookie() No value ' + name + ' - ' + value); return false; } // type of element where put data if(typeof type == 'undefined') { type = 'val'; } switch(type) { case 'val': _this.val(value); break; case 'select': $('option', _this).removeAttr('selected'); _this.val(value); $('option[value="'+value+'"]', _this).attr('selected', 'selected'); break; case 'theme-select': $('option', _this).removeA