/*! flypanels - v0.12.1 - 2015-06-17 * https://github.com/subzane/flypanels * copyright (c) 2015 andreas norman; licensed mit */ (function ($) { // change this to your plugin name. var pluginname = 'flypanels'; /** * plugin object constructor. * implements the revealing module pattern. */ function plugin(element, options) { // references to dom and jquery versions of element. var el = element; var $el = $(element); var innerheight = window.innerheight; var panelwidth; var redrawonresize = true; // need to get the topbar height in order to later set the correct height of .flypanels-content var topbarheight = parseint($('.flypanels-topbar').css('height'), 10); // default options for the tree menu component var treemenu = { init: false, expandhandler: 'a.expand' }; // extend default treemenu options with those supplied by user. options.treemenu = $.extend({}, treemenu, options.treemenu); // default options for the search component var search = { init: false, savequerycookie: false, searchpanel: $('.offcanvas').find('[data-panel="search"]') }; // extend default search options with those supplied by user. options.search = $.extend({}, search, options.search); // extend default options with those supplied by user. options = $.extend({}, $.fn[pluginname].defaults, options); /** * initialize plugin. */ function init() { setheight(); panelwidth = $('.flypanels-left').css('width'); attachevents(); if (options.search.init) { initsearch(); } if (options.treemenu.init) { inittreemenu(); } // remove preload class when page has loaded to allow transitions/animations $(document).ready(function () { $el.removeclass('preload'); }); hook('oninit'); } function setheight() { //$('.flypanels-content').css('height', (parseint(innerheight, 10) - topbarheight) + 'px'); $('.flypanels-left').css('height', innerheight); $('.flypanels-right').css('height', innerheight); $('.flypanels-overlay').css('height', innerheight); } function inittreemenu() { if (kitutils.isandroid() || kitutils.isios()) { $('.flypanels-treemenu').addclass('touch'); } $('.flypanels-treemenu li.haschildren ' + options.treemenu.expandhandler).click(function (e) { $(this).parent().parent().toggleclass('expanded'); e.preventdefault(); }); } function close() { closeleft(); closeright(); onclose(); } function oncloseleft() { $('body').removeclass('flypanels-open'); $('html').removeclass('flypanels-open'); hook('oncloseleft'); } function oncloseright() { $('body').removeclass('flypanels-open'); $('html').removeclass('flypanels-open'); hook('oncloseright'); } function onopenleft() { $('body').addclass('flypanels-open'); $('html').addclass('flypanels-open'); hook('onopenleft'); } function onopenright() { $('body').addclass('flypanels-open'); $('html').addclass('flypanels-open'); hook('onopenright'); } function onopen() { $('.flypanels-content').append('
'); $('.flypanels-content').on('click touchmove touchend touchleave touchcancel', function (e) { close(); e.preventdefault(); }); hook('onopen'); } function onclose() { $('.flypanels-content #flypanels-overlay').remove(); $('.flypanels-content').off('click touchmove touchend touchleave touchcancel'); hook('onclose'); } function openright(panel) { $el.addclass('openright'); settimeout(function () { $('.flypanels-right').find('[data-panel="' + panel + '"]').show(); onopenright(); onopen(); }, 140); } function closeright() { $el.removeclass('openright'); settimeout(function () { $('.offcanvas .panelcontent').hide(); oncloseright(); onclose(); }, 140); } function openleft(panel) { $el.addclass('openleft'); settimeout(function () { $('.flypanels-left').find('[data-panel="' + panel + '"]').show(); onopenleft(); onopen(); }, 140); } function closeleft() { $el.removeclass('openleft'); settimeout(function () { $('.offcanvas .panelcontent').hide(); oncloseleft(); onclose(); }, 140); } function afterwindowresize() { innerheight = window.innerheight; setheight(); } function initsearch() { if (kitutils.isandroid() || kitutils.isios()) { $('.flypanels-searchresult').addclass('touch'); } options.search.searchpanel.find('.searchbutton').on('click', function (event) { event.preventdefault(); searchprogress('show'); dosearch(options.search.searchpanel.find('.searchbox input').val()); }); options.search.searchpanel.find('.searchbox input').keydown(function (event) { if (event.which === 13) { searchprogress('show'); dosearch($(this).val()); $(this).blur(); } }); if (cookies.has('searchquery') === true && options.search.savequerycookie === true) { dosearch(cookies.get('searchquery')); } } function searcherror(state) { if (state === 'hide') { options.search.searchpanel.find('.errormsg').hide(); } else { options.search.searchpanel.find('.errormsg').show(); } } function searchprogress(state) { if (state === 'hide') { options.search.searchpanel.find('.loading').hide(); } else { options.search.searchpanel.find('.loading').show(); } } var cookies = { get: function (skey) { if (!skey) { return null; } return decodeuricomponent(document.cookie.replace(new regexp('(?:(?:^|.*;)\\s*' + encodeuricomponent(skey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1')) || null; }, set: function (skey, svalue, vend, spath, sdomain, bsecure) { if (!skey || /^(?:expires|max\-age|path|domain|secure)$/i.test(skey)) { return false; } var sexpires = ''; if (vend) { switch (vend.constructor) { case number: sexpires = vend === infinity ? '; expires=fri, 31 dec 9999 23:59:59 gmt' : '; max-age=' + vend; break; case string: sexpires = '; expires=' + vend; break; case date: sexpires = '; expires=' + vend.toutcstring(); break; } } document.cookie = encodeuricomponent(skey) + '=' + encodeuricomponent(svalue) + sexpires + (sdomain ? '; domain=' + sdomain : '') + (spath ? '; path=' + spath : '') + (bsecure ? '; secure' : ''); return true; }, remove: function (skey, spath, sdomain) { if (!this.hasitem(skey)) { return false; } document.cookie = encodeuricomponent(skey) + '=; expires=thu, 01 jan 1970 00:00:00 gmt' + (sdomain ? '; domain=' + sdomain : '') + (spath ? '; path=' + spath : ''); return true; }, has: function (skey) { if (!skey) { return false; } return (new regexp('(?:^|;\\s*)' + encodeuricomponent(skey).replace(/[\-\.\+\*]/g, '\\$&') + '\\s*\\=')).test(document.cookie); }, keys: function () { var akeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '').split(/\s*(?:\=[^;]*)?;\s*/); for (var nlen = akeys.length, nidx = 0; nidx < nlen; nidx++) { akeys[nidx] = decodeuricomponent(akeys[nidx]); } return akeys; } }; function dosearch(query) { searcherror('hide'); $jsonurl = options.search.searchpanel.find('.searchbox').data('searchurl'); $ajaxcall = $.ajax({ url: $jsonurl + '&q=' + query, datatype: 'json' }); // ajax success $ajaxcall.done(function (response) { var output; $foundresults = response.items.length; // check if any products found if ($foundresults > 0) { if (options.search.savequerycookie === true) { cookies.set('searchquery', query, null, '/'); } output = buildresultslist(response.items); } else { //$.removecookie('searchquery'); if (options.search.savequerycookie === true) { cookies.remove('searchquery', '/'); } searcherror('show'); } // render html options.search.searchpanel.find('.resultinfo .query').html(query); options.search.searchpanel.find('.resultinfo .num').html($foundresults); options.search.searchpanel.find('.flypanels-searchresult').html(output); searchprogress('hide'); options.search.searchpanel.find('.resultinfo').show(); options.search.searchpanel.find('.flypanels-searchresult').show(); }); // ajax error $ajaxcall.fail(function () { // render error message ***** should we get the error message from response.error? ***** // if so, include jqxhr and response in the fail function searcherror('show'); }); } function buildresultslist(results) { output = ''; return output; } function attachevents() { // prevent scroll if content doesn't need scroll. $('.panelcontent').on('touchmove', function (e) { if ($(this).prop('scrollheight') <= parseint(innerheight, 10)) { e.preventdefault(); } }); // prevent scrolling of the panel itself. only the content panel should be allowed to scroll $('.offcanvas').on('touchmove', function (e) { e.preventdefault(); }).on('touchmove', '.panelcontent', function (e) { e.stoppropagation(); }); $('.flypanels-button-left').on('click', function () { var panel = $(this).data('panel'); if ($('.flypanels-container').hasclass('openleft')) { closeleft(); } else { openleft(panel); } }); $('.flypanels-button-right').on('click', function () { var panel = $(this).data('panel'); if ($('.flypanels-container').hasclass('openright')) { closeright(); } else { openright(panel); } }); if (redrawonresize === true) { var resizetimer; $(window).resize(function () { cleartimeout(resizetimer); resizetimer = settimeout(afterwindowresize, 100); }); } // listen for orientation changes $(window).bind('orientationchange', function (e) { setheight(); }); hook('onload'); } /** * get/set a plugin option. * get usage: $('#el').flypanels('option', 'key'); * set usage: $('#el').flypanels('option', 'key', value); */ function option(key, val) { if (val) { options[key] = val; } else { return options[key]; } } /** * destroy plugin. * usage: $('#el').flypanels('destroy'); */ function destroy() { // iterate over each matching element. $el.each(function () { var el = this; var $el = $(this); // add code to restore the element to its original state... hook('ondestroy'); // remove plugin instance from the element. $el.removedata('plugin_' + pluginname); }); } /** * callback hooks. * usage: in the defaults object specify a callback function: * hookname: function() {} * then somewhere in the plugin trigger the callback: * hook('hookname'); */ function hook(hookname) { if (options[hookname] !== undefined) { // call the user defined function. // scope is set to the jquery element we are operating on. options[hookname].call(el); } } // initialize the plugin instance. init(); // expose methods of plugin we wish to be public. return { option: option, destroy: destroy, }; } /** * plugin definition. */ $.fn[pluginname] = function (options) { // if the first parameter is a string, treat this as a call to // a public method. if (typeof arguments[0] === 'string') { var methodname = arguments[0]; var args = array.prototype.slice.call(arguments, 1); var returnval; this.each(function () { // check that the element has a plugin instance, and that // the requested public method exists. if ($.data(this, 'plugin_' + pluginname) && typeof $.data(this, 'plugin_' + pluginname)[methodname] === 'function') { // call the method of the plugin instance, and pass it // the supplied arguments. returnval = $.data(this, 'plugin_' + pluginname)[methodname].apply(this, args); } else { throw new error('method ' + methodname + ' does not exist on jquery.' + pluginname); } }); if (returnval !== undefined) { // if the method returned a value, return the value. return returnval; } else { // otherwise, returning 'this' preserves chainability. return this; } // if the first parameter is an object (options), or was omitted, // instantiate a new instance of the plugin. } else if (typeof options === 'object' || !options) { return this.each(function () { // only allow the plugin to be instantiated once. if (!$.data(this, 'plugin_' + pluginname)) { // pass options to plugin constructor, and store plugin // instance in the elements jquery data object. $.data(this, 'plugin_' + pluginname, new plugin(this, options)); } }); } }; // default plugin options. // options can be overwritten when initializing plugin, by // passing an object literal, or after initialization: // $('#el').flypanels('option', 'key', value); $.fn[pluginname].defaults = { oninit: function () {}, onload: function () {}, onopenleft: function () {}, onopenright: function () {}, oncloseleft: function () {}, oncloseright: function () {}, ondestroy: function () {} }; })(jquery);