/* * Facebox-Bootstrap (for jQuery v1.2+ & Bootstrap v3) * version: 0.9 * * Licensed under the MIT: * http://www.opensource.org/licenses/mit-license.php * * Copyright Forever Chris Wanstrath, Kyle Neath, Michael Chaney * * Based on the awesomely simple "facebox" code by Chris Wanstrath, * later maintained by Kyle Neath. * * This is a simple shim to allow the standard Bootstrap modal to be * used in the same manner as the older "facebox" jquery plugin. The * main difference is that facebox - when given a link - will load the * remote resource each time it is called. The Bootstrap modal will * only load it one time. The Bootstrap modal also relies on having the * modal DOM in the document ready to be shown whereas the facebox code * only adds it when needed. * * To use this, simply remove facebox.js and facebox.css and drop this * in after you include Bootstrap's js. * * Note: this is meant to be a straight drop-in replacement. It should * work nicely if you do nothing else. However, I have specifically * created it so that you can update your code incrementally to fit * Bootstrap better as time permits. * * This shim simply creates the appropriate DOM object when invoked, * fills it in, and then uses the Bootstrap modal to show it. If * invoked in "straight" mode it'll pass the url directly to Bootstrap * and allow it to handle the ajax call to load data. Note that this is * not just like Bootstrap's regular call as this will load the data * afresh each time it's called. * * $.facebox.settings.compatibility = 'normal' * $.facebox.settings.compatibility = 'straight' * * In straight mode, URLs are handed off to Boostrap's standard code * which will load the data into the "modal-content" div. * * In normal mode facebox loads the data itself and examines it. If it * includes a "modal-body" div the data will be loaded directly into * "modal-content" as in straight mode. Otherwise it will be loaded * into a "modal-body" div. Furthermore, the first header of any kind * will be removed and its contents inserted into the "h4" in the * modal-header div. This standard modal also has a close "x" in the * header and a close button in the footer. * * All callbacks are mapped to Bootstrap modal callbacks: * * Bootstrap Facebox * * show.bs.modal loading.facebox, beforeReveal.facebox * shown.bs.modal reveal.facebox, afterReveal.facebox * hidden.bs.modal afterClose.facebox * * Also, you can trigger "close.facebox" manually to close the modal. * * This is the original documentation: * * Usage: * * jQuery(document).ready(function() { * jQuery('a[rel*=facebox]').facebox() * }) * * Terms * Loads the #terms div in the box * * Terms * Loads the terms.html page in the box * * Terms * Loads the terms.png image in the box * * * You can also use it programmatically: * * jQuery.facebox('some html') * jQuery.facebox('some html', 'my-groovy-style') * * The above will open a facebox with "some html" as the content. * * jQuery.facebox(function($) { * $.get('blah.html', function(data) { $.facebox(data) }) * }) * * The above will show a loading screen before the passed function is called, * allowing for a better ajaxy experience. * * The facebox function can also display an ajax page, an image, or the contents of a div: * * jQuery.facebox({ ajax: 'remote.html' }) * jQuery.facebox({ ajax: 'remote.html' }, 'my-groovy-style') * jQuery.facebox({ image: 'stairs.jpg' }) * jQuery.facebox({ image: 'stairs.jpg' }, 'my-groovy-style') * jQuery.facebox({ div: '#box' }) * jQuery.facebox({ div: '#box' }, 'my-groovy-style') * * Want to close the facebox? Trigger the 'close.facebox' document event: * * jQuery(document).trigger('close.facebox') * * Facebox also has a bunch of other hooks: * * loading.facebox * beforeReveal.facebox * reveal.facebox (aliased as 'afterReveal.facebox') * init.facebox * afterClose.facebox * * Simply bind a function to any of these hooks: * * $(document).bind('reveal.facebox', function() { ...stuff to do after the facebox and contents are revealed... }) * */ (function($) { $.facebox = function(data, klass) { $.facebox.loading(data.settings || []) if (data.ajax) fillFaceboxFromLink(data.ajax, klass) else if (data.image) fillFaceboxFromImage(data.image, klass) else if (data.div) fillFaceboxFromHref(data.div, klass) else if ($.isFunction(data)) data.call($) else $.facebox.reveal(data, klass) } /* * Public, $.facebox methods */ $.extend($.facebox, { settings: { modalSize : null, // null, 'large', or 'small' compatibility: 'normal', // straight or normal imageTypes : [ 'png', 'jpg', 'jpeg', 'gif' ], faceboxMinimalHtml : '\ \ ', faceboxHtml : '\ \ ' }, loading: function() { init() if ($.facebox.current_modal) return true; if ($.facebox.settings.compatibility=='straight') { $.facebox.current_modal = $($.facebox.settings.faceboxMinimalHtml); } else { $.facebox.current_modal = $($.facebox.settings.faceboxHtml); } if ($.facebox.settings.modalSize == 'small') { $.facebox.current_modal.find('.modal-dialog').addClass('modal-sm'); } else if ($.facebox.settings.modalSize == 'large') { $.facebox.current_modal.find('.modal-dialog').addClass('modal-lg'); } }, // In this case, show a remote link revealRemote: function(link, klass) { if (klass) $.facebox.current_modal.addClass(klass) $.facebox.current_modal.modal({remote: link}); }, // data is literal data to stick in the modal reveal: function(data, klass) { if (klass) $.facebox.current_modal.addClass(klass) $.facebox.current_modal.find('.modal-body').append(data); $.facebox.current_modal.modal(); }, // Takes literal data and examines it. If the literal data has a // "modal-body" div, then the data will replace the entire // "modal-content" div of the modal. Otherwise, the data will be // stuck into "modal-body". Additionally, the first header (h1-h6) // will be removed and its contents put into an h4 in the modal // header. revealNormal: function(data, klass) { if (klass) $.facebox.current_modal.addClass(klass) if (data.match(/class\s*=\s*["']modal-body/)) { $.facebox.current_modal.find('.modal-content').empty().append(data); } else { var header_match_data = data.match(/<(h[123456]).*?>(.*?)(<\/\1>)/); if (header_match_data) { $.facebox.current_modal.find('.modal-header h4').empty().append(header_match_data[2]); data = data.replace(new RegExp(header_match_data[0]),''); } else { $.facebox.current_modal.find('.modal-header h4').remove(); } $.facebox.current_modal.find('.modal-body').append(data); } $.facebox.current_modal.modal(); }, close: function() { $(document).trigger('close.facebox') return false } }) /* * Public, $.fn methods */ $.fn.facebox = function(settings) { if ($(this).length == 0) return init(settings) function clickHandler() { $.facebox.loading(true) // support for rel="facebox.inline_popup" syntax, to add a class // also supports deprecated "facebox[.inline_popup]" syntax var klass = this.rel.match(/facebox\[?\.(\w+)\]?/) if (klass) klass = klass[1] fillFaceboxFromHref(this.href, klass) return false } return this.bind('click.facebox', clickHandler) } /* * Private methods */ // called one time to setup facebox on this page function init(settings) { if ($.facebox.settings.inited) return true else $.facebox.settings.inited = true $(document).trigger('init.facebox') makeCompatible() var imageTypes = $.facebox.settings.imageTypes.join('|') $.facebox.settings.imageTypesRegexp = new RegExp('\\.(' + imageTypes + ')(\\?.*)?$', 'i') // This will hold the current modal $.facebox.current_modal = null; if (settings) $.extend($.facebox.settings, settings) $(document).on('show.bs.modal', function() { $(document).trigger('loading.facebox').trigger('beforeReveal.facebox'); }); $(document).on('shown.bs.modal', function() { $(document).trigger('reveal.facebox').trigger('afterReveal.facebox') }); $(document).on('hidden.bs.modal', function() { $(document).trigger('afterClose.facebox'); $.facebox.current_modal.remove(); $.facebox.current_modal = null; }); } // Backwards compatibility function makeCompatible() { var $s = $.facebox.settings $s.loadingImage = $s.loading_image || $s.loadingImage $s.closeImage = $s.close_image || $s.closeImage $s.imageTypes = $s.image_types || $s.imageTypes $s.faceboxHtml = $s.facebox_html || $s.faceboxHtml } // Figures out what you want to display and displays it // formats are: // div: #id // image: blah.extension // ajax: anything else function fillFaceboxFromHref(href, klass) { // div if (href.match(/#/)) { var url = window.location.href.split('#')[0] var target = href.replace(url,'') if (target == '#') return $.facebox.reveal($(target).html(), klass) // image } else if (href.match($.facebox.settings.imageTypesRegexp)) { fillFaceboxFromImage(href, klass) // ajax } else { fillFaceboxFromLink(href, klass) } } function fillFaceboxFromImage(href, klass) { var image = new Image() image.onload = function() { $.facebox.reveal('
', klass) } image.src = href } function fillFaceboxFromLink(href, klass) { if ($.facebox.settings.compatibility == 'normal') { $.facebox.jqxhr = $.get(href, function(data) { $.facebox.revealNormal(data, klass) }, 'text'); } else { $.facebox.revealRemote(href, klass); } } /* * Bindings */ $(document).bind('close.facebox', function() { $.facebox.current_modal.modal('hide'); }); })(jQuery);