UNPKG

nk-lightbox

Version:
610 lines (510 loc) 19.5 kB
/** * Close on layer touchstart supported */ // JavaScript Document if (!model) { var model = function () { var isTransitionEndSupported = function () { var transEndEventNames = { WebkitTransition: 'webkitTransitionEnd', MozTransition: 'transitionend', OTransition: 'oTransitionEnd otransitionend', transition: 'transitionend' }; for (var name in transEndEventNames) { if (document.documentElement.style[name] !== undefined) { return transEndEventNames[name]; } } }(); if (DEBUG) { window.isTransitionEndSupported = isTransitionEndSupported; } //Refered : JQuery UI Code //Detects focusable element /*function focusable(element, isTabIndexNotNaN) { var map, mapName, img, nodeName = element.nodeName.toLowerCase(); if ("area" === nodeName) { map = element.parentNode; mapName = map.name; if (!element.href || !mapName || map.nodeName.toLowerCase() !== "map") { return false; } img = $("img[usemap=#" + mapName + "]")[0]; return !!img && visible(img); } return (/input|select|textarea|button|object/.test(nodeName) ? !element.disabled : "a" === nodeName ? element.href || isTabIndexNotNaN : isTabIndexNotNaN) && // the element and all of its ancestors must be visible visible(element); } function visible(element) { return $.expr.filters.visible(element) && !$(element).parents().addBack().filter(function () { return $.css(this, "visibility") === "hidden"; }).length; } $.expr[":"].focusable = function (element) { return focusable(element, !isNaN($.attr(element, "tabindex"))); };*/ //Refered : JQuery UI Code /** Some common Utility functions*/ var util = { is_options_valid: function (options) { if (!options || !options.model || options.model[0]['nodeType'] !== 1) { return false; } return true; }, switchClass: function (a, b) { window.requestAnimationFrame(function () { this.removeClass(a).addClass(b); }.bind(this)); } }; if (DEBUG) { window.util = util; } var default_opt = { model: null, dimens: { height: 'auto', width: 'auto' }, resetForm: false, fixed: false, zLayer: true, open: { minZIndex: 999, success: function () {}, event: 'click', selector: null, anim: '' // anim : {className:''} }, close: { esc: true, layer: true, nodes: { target: '', event: 'click', selector: '' }, success: function () {}, returnFocus: true, anim: '' // anim : {className:'',duration:0} } }; /** Runs once */ var lt = function () { var cont = $('<div class="ltCont close"></div>').attr('tabIndex', 0); var layer = $('<div class="ltLayer close"></div>'); cont.append(layer); //Reset lightBox on resize $(window).on('resize', function () { if (lt.stack.length) { var top = lt.stack[0]; top.resize(); } }); //Close lightBox on close $('html').keydown(function (event) { if (event.keyCode === 27 && lt.stack.length && lt.stack[0].options.close.esc) { lt.stack[0].close_target = event; lt.stack[0].close(); } }); //Close lightBox on layer click layer.on("touchstart click", function (e) { e.preventDefault(); if (lt.stack.length && lt.stack[0].options.close.layer) { lt.stack[0].close_target = this; lt.stack[0].close(); } }); return { //Top most visible lightbox is lt.stack[0] stack: [], cont: cont, layer: layer }; }(); if (DEBUG) { window.stack = lt.stack; } //Document Ready //$(document).ready(function () { $('body').append(lt.cont); //}); /*var manage_focus = (function () { // If tab is pressend on or in lightbox lt.cont.keydown(function (event) { if (!lt.stack.length || event.keyCode !== 9){ return; } var list = lt.stack[0].options.model.find(':focusable'); var first = list.first(); var last = list.last(); if ((event.target === last[0] || event.target === event.currentTarget) && !event.shiftKey) { first ? first.focus() : ''; return false; } else if ((event.target === first[0] || event.target === event.currentTarget) && event.shiftKey) { last ? last.focus() : ''; return false; } event.stopPropagation(); }); // If tab is pressed on first or last focusable element and lightbox is open $('html').keydown(function (event) { if (event.keyCode !== 9){ return;} // If lightbox is open if (lt.stack.length) { lt.cont.focus(); return false; } }); }());*/ //for findOut max ZIndex on page // * is replaced with .ltLayer as multiple ltCont are created when lightBox.js is included more than once. function getMaxZIndex() { var zIndexMax = this.options.open.minZIndex; $('.ltCont .ltLayer').each(function () { var z = parseInt($(this).css('z-index')); if (z > zIndexMax) zIndexMax = z; }); return zIndexMax; } var init_Dimensions = function () { this.options.model.css({ position: this.options.fixed ? 'fixed' : 'absolute', width: this.options.dimens.width, height: this.options.dimens.height }); }; var init_options = function (param) { this.options = $.extend(true, {}, this.default_opt, param); }; var init_structure = function () { var parent = this.options.model.parent(); /** Check if lightBox alerady present in ltCont */ if (!parent.hasClass('ltCont')) { lt.cont.append(this.options.model); } }; var animate = { open: function () { var arr = [this.options.close.anim, this.options.open.anim]; util.switchClass.apply(this.options.model, arr); }, close: function (obj) { var arr = [this.options.open.anim, this.options.close.anim]; util.switchClass.apply(this.options.model, arr); } }; var open_firstFocus = function () { /** IE specific fix, for scroll move on focus*/ //var scrollTop = document.documentElement.scrollTop; var ff = this.options.open.firstFocus; if (ff) ff.focus();else lt.cont.focus(); /** IE specific fix, for scroll move on focus*/ //document.documentElement.scrollTop = scrollTop; }; var resetForm = function () { if (!this.options.resetForm) return; var forms = this.options.model.find('form'); for (var key = 0; key < forms.length; key++) { forms[key].reset(); } }; var close_returnFocus = function () { if (!lt.stack.length) { var rf = this.options.close.returnFocus; rf === true ? this.options.trigger.focus() : $(rf).focus(); } }; var closeTransEnd_cb = function () { this.options.model.removeClass('model_open'); //this.options.model.css('zIndex', '-1'); if (lt.stack.length) { var top = lt.stack[0]; if (this.options.zLayer) { lt.layer.css('zIndex', top.options.model.css('zIndex')); } } else { lt.cont.addClass('close'); } close_returnFocus.call(this); resetForm.call(this); this.options.close.success.call(this, this.close_target); }; var init_openclose_Properties = function () { var _this = this; _this.state = "close"; /** Adding event on trigger */ this.openEventHandler = function () { _this.open(); }; on.call(this); //this.options.trigger.on(this.options.open.event + '.' + this.pluginName,this.options.open.selector, this.openEventHandler) /**Adding events Closing nodes */ init_closeNodes.call(this, this.options.close.nodes); }; var init_closeNodes = function (nodes) { var _this = this; this.close_target = null; if ($.type(nodes) === 'array') { //Recursive $.each(nodes, function (a, b) { init_closeNodes.call(_this, b); }); return; } var config = null; if ("on" in nodes) { config = $.extend({}, this.default_opt.close.nodes); config.target = nodes; } else { config = { target: $(nodes.target), event: nodes.event, selector: nodes.selector }; } config.target.on(config.event, config.selector, function () { _this.close(); _this.close_target = this; }); }; /** Run every time a new lightbox is created */ var init = function (param) { init_options.call(this, param); this.init_structure(); init_Dimensions.call(this); init_openclose_Properties.call(this); this.options.model.addClass(this.options.close.anim); }; var reInit = function (pluginName) { this.options.trigger.off(this.options.open.event + '.' + this.pluginName); }; var off = function () { //this.options.trigger.off(this.options.open.event, this.openEventHandler); this.options.trigger.off(this.options.open.event + '.' + this.pluginName, this.options.open.selector, this.openEventHandler); }; var on = function () { //this.options.trigger.on(this.options.open.event, this.openEventHandler); this.options.trigger.on(this.options.open.event + '.' + this.pluginName, this.options.open.selector, this.openEventHandler); }; /** To be overrited */ var resize = function () { model.lt.cont.css({ width: 'auto', height: 'auto' }); var totalH = $(document).height(), totalW = $(document).width(); model.lt.cont.css({ width: totalW + 'px', height: totalH + 'px' }); }; var open = function () { this.close_target = null; this.state = 'open'; this.options.model.addClass('model_open'); this.options.model[0]['model'] = this; /** Setting zIndex of lightBox and black layer */ var maxZIndElm = getMaxZIndex.call(this); if (this.options.zLayer) { lt.layer.css('zIndex', maxZIndElm + 3); } if (this.pluginName != 'drawer') { this.options.model.css('zIndex', maxZIndElm + 3); } if (!lt.stack.length) { lt.cont.css('zIndex', maxZIndElm + 1); this.util.switchClass.call(lt.layer, 'close', 'open'); lt.cont.removeClass('close'); } resetForm.call(this); /** Stack Update */ if ($.inArray(this, lt.stack) === -1) { lt.stack.unshift(this); } /** Center align LightBox */ this.resize(); /** Animation Code */ animate.open.call(this); /** Focus Element */ open_firstFocus.call(this); /** Success callback */ this.options.open.success.call(this); }; var close = function (index, noAnim) { index = index || $(lt.stack).index(this); if (!lt.stack.length || index < 0) return; this.state = 'close'; this.options.model[0]['model'] = this; lt.stack.splice(index, 1); if (!isTransitionEndSupported || noAnim || !this.options.open.anim) { closeTransEnd_cb.call(this); } else { animate.close.call(this); } if (!lt.stack.length) this.util.switchClass.call(lt.layer, 'open', 'close'); }; var destroy = function () { this.off(); close.call(this, undefined, true); if (!lt.stack.length) { this.util.switchClass.call(lt.layer, 'open', 'close'); lt.cont.addClass('close'); } this.options.model.remove(); }; var getNewModel = function (pluginName) { var _const = function () {}; _const.prototype = model; var _proto_subModel = new _const(); _proto_subModel.pluginName = pluginName; function _const_subModel(options, trigger) { /** Cleaning registered events for same trigger-lightBox*/ var obj = trigger.data('model'); if (obj && obj.options && obj.options.model[0] === options.model[0]) { reInit.call(this); } options.trigger = trigger; init.call(this, options); } _const_subModel.prototype = _proto_subModel; return _const_subModel; }; return { isTransitionEndSupported: isTransitionEndSupported, pluginName: '', state: 'close', util: util, lt: lt, reInit: reInit, close_returnFocus: close_returnFocus, getNewModel: getNewModel, open: open, close: close, on: on, off: off, resize: resize, default_opt: default_opt, init_structure: init_structure, closeTransEnd_cb: closeTransEnd_cb, destroy: destroy }; }(); } /** * ltCont height set to calc(100% + 60px) * ltCont width set to windows width */ /* jslint curly : false */ /* jslint asi : true */ /*global pageXOffset */ /*global pageYOffset */ /*Start of Drawer Model*/ (function ($) { /** Singleton Pattern */ /** If options are given each time a new object will be returned otherwise last configure object will be returend */ var pluginName = 'drawer'; var default_opt = { "dir": "right", "open": { "anim": "sideIn" }, "zLayer": false, "close": { "anim": "sideOut" /*Empty class required*/ } }; var drawer = model.getNewModel(pluginName); drawer.prototype.default_opt = $.extend(true, {}, model.default_opt, default_opt); drawer.prototype.init_structure = function () { model.init_structure.call(this); this.options.model.addClass(this.options.dir); }; drawer.prototype.resize = function () { var minHeight = parseInt($('body').css('minHeight') || 0); model.lt.cont.css({ width: 'auto', height: 'auto' }); //var totalH = Math.max(minHeight,$(window).height()), var totalH = $(window).height(), totalW = $(window).width(); /* this.options.contentWrapper.css({ width: totalW + 'px', height: totalH + 'px' }); */ model.lt.cont.css({ width: totalW + 'px', height: totalH + 'px' }); }; /** Wrapped to handle drawer open and close */ var drawer_open = function () { model.open.call(this); }; var drawer_close = function () { model.close.call(this); }; $.fn.drawer = function (options) { var obj = null, mask = null; if (model.util.is_options_valid(options)) { $.each(this, function (a, b) { var _this = $(b); obj = new drawer(options, _this); obj.open = function () { drawer_open.call(obj); $('html,body').addClass('drawerDisableScroll'); }; obj.close = function () { drawer_close.call(obj); if (model.lt.stack.length == 0) { $('html,body').removeClass('drawerDisableScroll'); } }; mask = { open: obj.open, close: obj.close, on: function () { obj.on(); }, off: function () { obj.off(); }, destroy: function () { obj.destroy(); if (model.lt.stack.length == 0) { $('html,body').removeClass('drawerDisableScroll'); } } }; _this[0].model = mask; }); var optionModel = options.model; optionModel.on(model.isTransitionEndSupported, function (e) { if (e.target == optionModel[0]) { if (optionModel.hasClass(obj.options.close.anim)) { model.closeTransEnd_cb.call(obj); } } }); } return this[0].model || obj; }; })(Zepto); /*End of Drawer Model*/ /** * drawer-zepto_v3.js * drawerDisableScroll : Class toggled on opening and closing drawer * Removed code to set height of ltCont to maximum of body minHeight or window height */