diff --git a/README.md b/README.md index 656fedc..fb84d8f 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ close_aria_label|`string`|`Close (Press escape to close)`||String for close butt width|`integer`|null||Set the desired width of the modal. height|`integer`|null||Set the desired height of the modal. gallery_active_class|`string`|`gallery_active_item`||Active class applied to the currently active image or image slide in a gallery +loop_gallery|`boolean`|`false`|`true`
`false`|Set to true to allow the gallery to loop between the last and first image slides. outer_controls|`boolean`|`false`|`true`
`false`|Set to true to put the next/prev controls outside the Modaal wrapper, at the edges of the browser window. confirm_button_text|`string`|`Confirm`||Text on the confirm button. confirm_cancel_button_text|`string`|`Cancel`||Text on the confirm modal cancel button. diff --git a/dist/js/modaal.js b/dist/js/modaal.js index 646cbc2..bbffcda 100644 --- a/dist/js/modaal.js +++ b/dist/js/modaal.js @@ -65,6 +65,7 @@ === Gallery Options & Events === gallery_active_class (string) : Active class applied to the currently active image or image slide in a gallery 'gallery_active_item' + loop_gallery (boolean) : Set to true to allow the gallery to loop between the last and first image slides. outer_controls (boolean) : Set to true to put the next/prev controls outside the Modaal wrapper, at the edges of the browser window. before_image_change (function) : Callback function executed before the image slide changes in a gallery modal. Default function( current_item, incoming_item ) after_image_change (function) : Callback function executed after the image slide changes in a gallery modal. Default function ( current_item ) @@ -378,7 +379,7 @@ } // add the guts of the content - build_markup += '",t.build_modal(a)},create_image:function(){var t,o,e=this,i=e.options.loop_gallery,l="";if(e.$elem.is("[data-group]")||e.$elem.is("[rel]")){var n=e.$elem.is("[data-group]"),s=n?e.$elem.attr("data-group"):e.$elem.attr("rel"),d=a(n?'[data-group="'+s+'"]':'[rel="'+s+'"]');d.removeAttr("data-gallery-active","is_active"),e.$elem.attr("data-gallery-active","is_active"),o=d.length-1;var r=[];l='",1!=e.options.outer_controls&&(l+=e.scope.prev_btn+e.scope.next_btn)}else{var _,v=!1;e.$elem.attr("data-modaal-content-source")?_=e.$elem.attr("data-modaal-content-source"):e.$elem.attr("href")?_=e.$elem.attr("href"):e.$elem.attr("src")?_=e.$elem.attr("src"):(_="trigger requires href or data-modaal-content-source attribute",v=!0);var f="",g="",p="";e.$elem.attr("data-modaal-desc")?(p=e.$elem.attr("data-modaal-desc"),f=e.$elem.attr("data-modaal-desc"),g='"):p="Image with no description";var u=v?_:' ';l='"}t=l,e.build_modal(t),!i&&a(".modaal-gallery-item.is_active").is(".gallery-item-0")&&a(".modaal-gallery-prev").hide(),!i&&a(".modaal-gallery-item.is_active").is(".gallery-item-"+o)&&a(".modaal-gallery-next").hide()},gallery_update:function(t){var o=this,e=a("#"+o.scope.id),i=e.find(".modaal-gallery-item"),l=i.length-1,n=o.options.loop_gallery;if(0==l)return!1;var s,d=e.find(".modaal-gallery-prev"),r=e.find(".modaal-gallery-next"),c=0,m=0,p=e.find(".modaal-gallery-item."+o.private_options.active_class);if("prev"==t)if(e.find(".gallery-item-0").hasClass("is_active")){if(!n)return!1;s=p.parent().find("> div:last-child")}else s=p.prev(".modaal-gallery-item");else if("next"==t)if(e.find(".gallery-item-"+l).hasClass("is_active")){if(!n)return!1;s=p.parent().find("> div:first-child")}else s=p.next(".modaal-gallery-item");o.options.before_image_change.call(o,p,s),p.stop().animate({opacity:0},250,function(){s.addClass("is_next").css({position:"absolute",display:"block",opacity:0});var t=a(document).width(),i=t>1140?280:50;c=e.find(".modaal-gallery-item.is_next").width(),m=e.find(".modaal-gallery-item.is_next").height();var u=e.find(".modaal-gallery-item.is_next img").prop("naturalWidth"),_=e.find(".modaal-gallery-item.is_next img").prop("naturalHeight");u>t-i?(c=t-i,e.find(".modaal-gallery-item.is_next").css({width:c}),e.find(".modaal-gallery-item.is_next img").css({width:c}),m=e.find(".modaal-gallery-item.is_next").find("img").height()):(c=u,m=_),e.find(".modaal-gallery-item-wrap").stop().animate({width:c,height:m},250,function(){p.removeClass(o.private_options.active_class+" "+o.options.gallery_active_class).removeAttr("style"),p.find("img").removeAttr("style"),s.addClass(o.private_options.active_class+" "+o.options.gallery_active_class).removeClass("is_next").css("position",""),s.stop().animate({opacity:1},250,function(){a(this).removeAttr("style").css({width:"100%"}),a(this).find("img").css("width","100%"),e.find(".modaal-gallery-item-wrap").removeAttr("style"),o.options.after_image_change.call(o,s)}),e.find(".modaal-gallery-item").removeAttr("tabindex"),e.find(".modaal-gallery-item."+o.private_options.active_class).attr("tabindex","0").focus(),!n&&e.find(".modaal-gallery-item."+o.private_options.active_class).is(".gallery-item-0")?d.stop().animate({opacity:0},150,function(){a(this).hide()}):d.stop().css({display:"block",opacity:d.css("opacity")}).animate({opacity:1},150),!n&&e.find(".modaal-gallery-item."+o.private_options.active_class).is(".gallery-item-"+l)?r.stop().animate({opacity:0},150,function(){a(this).hide()}):r.stop().css({display:"block",opacity:d.css("opacity")}).animate({opacity:1},150)})})},create_video:function(a){var t,o=this;t='',o.build_modal('
'+t+"
")},create_iframe:function(a){var t,o=this;t=null!==o.options.width||void 0!==o.options.width||null!==o.options.height||void 0!==o.options.height?'':'
Please specify a width and height for your iframe
',o.build_modal(t)},modaal_open:function(){var t=this,o=a("#"+t.scope.id),e=t.options.animation;"none"===e&&(o.removeClass("modaal-start_none"),t.options.after_open.call(t,o)),"fade"===e&&o.removeClass("modaal-start_fade"),"slide-down"===e&&o.removeClass("modaal-start_slide_down");var i=o;a(".modaal-wrapper *[tabindex=0]").removeAttr("tabindex"),i="image"==t.options.type?a("#"+t.scope.id).find(".modaal-gallery-item."+t.private_options.active_class):o.find(".modaal-iframe-elem").length?o.find(".modaal-iframe-elem"):o.find(".modaal-video-wrap").length?o.find(".modaal-video-wrap"):o.find(".modaal-focus"),i.attr("tabindex","0").focus(),t.is_ios()&&setTimeout(function(){i.find('[role="document"] >:first-child').focus()},1e3),"none"!==e&&setTimeout(function(){t.options.after_open.call(t,o)},t.options.after_callback_delay)},modaal_close:function(){var t=this,o=a("#"+t.scope.id);t.options.before_close.call(t,o),null!==t.xhr&&(t.xhr.abort(),t.xhr=null),"none"===t.options.animation&&o.addClass("modaal-start_none"),"fade"===t.options.animation&&o.addClass("modaal-start_fade"),"slide-down"===t.options.animation&&o.addClass("modaal-start_slide_down"),setTimeout(function(){"inline"==t.options.type&&a("#"+t.scope.id+" .modaal-content-container").contents().detach().appendTo(t.scope.source),o.remove(),t.options.after_close.call(t),t.scope.is_open=!1},t.options.after_callback_delay),t.modaal_overlay("hide"),null!=t.lastFocus&&t.lastFocus.focus(),t.is_ios()&&setTimeout(function(){null!=t.lastFocus&&t.lastFocus.focus()},1e3)},modaal_overlay:function(t){var o=this;"show"==t?(o.scope.is_open=!0,o.options.background_scroll||o.dom.addClass("modaal-noscroll"),a("#"+o.scope.id+"_overlay").length<1&&o.dom.append('
'),a("#"+o.scope.id+"_overlay").css("background",o.options.background).stop().animate({opacity:o.options.overlay_opacity},o.options.animation_speed,function(){o.modaal_open()})):"hide"==t&&a("#"+o.scope.id+"_overlay").stop().animate({opacity:0},o.options.animation_speed,function(){a(this).remove(),o.dom.removeClass("modaal-noscroll")})},is_touch:function(){return"ontouchstart"in window||navigator.maxTouchPoints},is_ios:function(){var a=navigator.userAgent;return!!(a.match(/iPhone/i)||a.match(/iPad/i)||a.match(/iPod/i))}},e=[];a.fn.modaal=function(t){return this.each(function(i){var l=a(this).data("modaal");if(l){if("string"==typeof t)switch(t){case"open":l.create_modaal(l);break;case"close":l.modaal_close()}}else{var n=Object.create(o);n.init(t,this),a.data(this,"modaal",n),e.push({element:a(this).attr("class"),options:t})}})},a.fn.modaal.options={type:"inline",content_source:null,animation:"fade",animation_speed:300,after_callback_delay:350,is_locked:!1,hide_close:!1,background:"#000",overlay_opacity:"0.8",overlay_close:!0,accessible_title:"Dialog Window",start_open:!1,fullscreen:!1,custom_class:"",background_scroll:!1,should_open:!0,close_text:"Close",close_aria_label:"Close (Press escape to close)",width:null,height:null,before_open:function(){},after_open:function(){},before_close:function(){},after_close:function(){},source:function(a,t){return t},confirm_button_text:"Confirm",confirm_cancel_button_text:"Cancel",confirm_title:"Confirm Title",confirm_content:"

This is the default confirm dialog content. Replace me through the options

",confirm_callback:function(){},confirm_cancel_callback:function(){},gallery_active_class:"gallery_active_item",loop_gallery:!1,outer_controls:!1,before_image_change:function(a,t){},after_image_change:function(a){},loading_content:'
',loading_class:"is_loading",ajax_error_class:"modaal-error",ajax_success:function(){},instagram_id:null},a(function(){var o=a(".modaal");o.length&&o.each(function(){t(a(this))});var i=new MutationObserver(function(o){o.forEach(function(o){if(o.addedNodes&&o.addedNodes.length>0){[].some.call(o.addedNodes,function(o){var i=a(o);(i.is("a")||i.is("button"))&&(i.hasClass("modaal")?t(i):e.forEach(function(t){if(t.element==i.attr("class"))return a(i).modaal(t.options),!1}))})}})}),l={subtree:!0,attributes:!0,childList:!0,characterData:!0};setTimeout(function(){i.observe(document.body,l)},500)})}(jQuery,window,document); \ No newline at end of file diff --git a/source/js/modaal.js b/source/js/modaal.js index 38860fc..bbffcda 100644 --- a/source/js/modaal.js +++ b/source/js/modaal.js @@ -65,6 +65,7 @@ === Gallery Options & Events === gallery_active_class (string) : Active class applied to the currently active image or image slide in a gallery 'gallery_active_item' + loop_gallery (boolean) : Set to true to allow the gallery to loop between the last and first image slides. outer_controls (boolean) : Set to true to put the next/prev controls outside the Modaal wrapper, at the edges of the browser window. before_image_change (function) : Callback function executed before the image slide changes in a gallery modal. Default function( current_item, incoming_item ) after_image_change (function) : Callback function executed after the image slide changes in a gallery modal. Default function ( current_item ) @@ -573,6 +574,7 @@ create_image : function() { var self = this; var content; + var loop_gallery = self.options.loop_gallery; var modaal_image_markup = ''; var gallery_total; @@ -721,10 +723,10 @@ self.build_modal(content); // setup next & prev buttons - if ( $('.modaal-gallery-item.is_active').is('.gallery-item-0') ) { + if ( !loop_gallery && $('.modaal-gallery-item.is_active').is('.gallery-item-0') ) { $('.modaal-gallery-prev').hide(); } - if ( $('.modaal-gallery-item.is_active').is('.gallery-item-' + gallery_total) ) { + if ( !loop_gallery && $('.modaal-gallery-item.is_active').is('.gallery-item-' + gallery_total) ) { $('.modaal-gallery-next').hide(); } }, @@ -736,6 +738,7 @@ var this_gallery = $('#' + self.scope.id); var this_gallery_item = this_gallery.find('.modaal-gallery-item'); var this_gallery_total = this_gallery_item.length - 1; + var loop_gallery = self.options.loop_gallery; // if single item, don't proceed if ( this_gallery_total == 0 ) { @@ -752,16 +755,36 @@ // CB: Before image change var current_item = this_gallery.find( '.modaal-gallery-item.' + self.private_options.active_class ), - incoming_item = ( direction == 'next' ? current_item.next( '.modaal-gallery-item' ) : current_item.prev( '.modaal-gallery-item' ) ); - self.options.before_image_change.call(self, current_item, incoming_item); - - // stop change if at start of end - if ( direction == 'prev' && this_gallery.find('.gallery-item-0').hasClass('is_active') ) { - return false; - } else if ( direction == 'next' && this_gallery.find('.gallery-item-' + this_gallery_total).hasClass('is_active') ) { - return false; + incoming_item; + + if ( direction == 'prev') { + // If it's the first item + if (this_gallery.find('.gallery-item-0').hasClass('is_active')) { + // If looping is set then move to the last slide + if (loop_gallery) { + incoming_item = current_item.parent().find('> div:last-child'); + } else { + return false; + } + } else { + incoming_item = current_item.prev( '.modaal-gallery-item' ); + } + } else if ( direction == 'next') { + // If it's the last item + if (this_gallery.find('.gallery-item-' + this_gallery_total).hasClass('is_active')) { + // If looping is set then move to the first slide + if (loop_gallery) { + incoming_item = current_item.parent().find('> div:first-child'); + } else { + return false; + } + } else { + incoming_item = current_item.next( '.modaal-gallery-item' ); + } } + self.options.before_image_change.call(self, current_item, incoming_item); + // lock dimensions current_item.stop().animate({ @@ -835,7 +858,7 @@ this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class + '').attr('tabindex', '0').focus(); // hide/show next/prev - if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-0') ) { + if ( !loop_gallery && this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-0') ) { prev_btn.stop().animate({ opacity: 0 }, 150, function(){ @@ -849,7 +872,7 @@ opacity: 1 }, 150); } - if ( this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-' + this_gallery_total) ) { + if ( !loop_gallery && this_gallery.find('.modaal-gallery-item.' + self.private_options.active_class).is('.gallery-item-' + this_gallery_total) ) { next_btn.stop().animate({ opacity: 0 }, 150, function(){ @@ -1166,6 +1189,7 @@ //Gallery Modal gallery_active_class: 'gallery_active_item', + loop_gallery: false, outer_controls: false, before_image_change: function( current_item, incoming_item ) {}, after_image_change: function( current_item ) {}, @@ -1332,6 +1356,12 @@ options.gallery_active_class = self.attr('data-modaal-gallery-active-class'); } + // option: loop_gallery + if ( self.attr('data-modaal-loop-gallery') ) { + inline_options = true; + options.loop_gallery = self.attr('data-modaal-loop-gallery'); + } + // option: loading_content if ( self.attr('data-modaal-loading-content') ) { inline_options = true;