diff options
author | Theo Chatzimichos <tampakrap@gentoo.org> | 2013-03-10 12:10:26 +0100 |
---|---|---|
committer | Theo Chatzimichos <tampakrap@gentoo.org> | 2013-03-10 12:10:26 +0100 |
commit | 7aea9fc04bd42e2ac02a1925d3a02a76d391c3e7 (patch) | |
tree | 68c852c654cef340592f1001b6310e33827b130c /plugins/jetpack/modules/shortcodes | |
parent | Make the script more silent (diff) | |
download | blogs-gentoo-7aea9fc04bd42e2ac02a1925d3a02a76d391c3e7.tar.gz blogs-gentoo-7aea9fc04bd42e2ac02a1925d3a02a76d391c3e7.tar.bz2 blogs-gentoo-7aea9fc04bd42e2ac02a1925d3a02a76d391c3e7.zip |
update plugins
Diffstat (limited to 'plugins/jetpack/modules/shortcodes')
17 files changed, 2706 insertions, 102 deletions
diff --git a/plugins/jetpack/modules/shortcodes/audio.php b/plugins/jetpack/modules/shortcodes/audio.php index 7b507a5f..9c6b49eb 100644 --- a/plugins/jetpack/modules/shortcodes/audio.php +++ b/plugins/jetpack/modules/shortcodes/audio.php @@ -6,7 +6,7 @@ class AudioShortcode { static $add_script = false; - + /** * Add all the actions & resgister the shortcode */ @@ -161,8 +161,8 @@ class AudioShortcode { // generate default titles $file_titles = array(); - for ( $i = 0; $i < $num_files; $i++ ) { - $file_titles[] = 'Track #' . ($i+1); + for ( $i = 0; $i < $num_files; $i++ ) { + $file_titles[] = 'Track #' . ($i+1); } // replace with real titles if they exist @@ -190,7 +190,7 @@ class AudioShortcode { $to_remove = array(); foreach ( $sound_files as $i => $sfile ) { $file_extension = pathinfo( $sfile, PATHINFO_EXTENSION ); - if ( ! preg_match( '/^(mp3|wav|ogg|oga|m4a|aac|webm)$/', $file_extension ) ) { + if ( ! preg_match( '/^(mp3|wav|ogg|oga|m4a|aac|webm)$/i', $file_extension ) ) { $html5_audio .= '<!-- Audio shortcode unsupported audio format -->'; if ( 1 == $num_files ) { $html5_audio .= $not_supported; @@ -199,7 +199,7 @@ class AudioShortcode { $to_remove[] = $i; // make a note of the bad files $all_mp3 = false; continue; - } elseif ( ! preg_match( '/^mp3$/', $file_extension ) ) { + } elseif ( ! preg_match( '/^mp3$/i', $file_extension ) ) { $all_mp3 = false; } @@ -240,9 +240,9 @@ CONTROLS; // override html5 audio code w/ just not supported code if ( is_feed() ) { $html5_audio = $not_supported; - } + } - if ( $all_mp3 ) { + if ( $all_mp3 ) { // process regular flash player, inserting HTML5 tags into object as fallback $audio_tags = <<<FLASH <object id='wp-as-{$post->ID}_{$ap_playerID}-flash' type='application/x-shockwave-flash' data='$swfurl' width='$width' height='24'> @@ -268,7 +268,7 @@ FLASH; // mashup the artist/titles for the script $script_titles = array(); - for ( $i = 0; $i < $num_files; $i++ ) { + for ( $i = 0; $i < $num_files; $i++ ) { $script_titles[] = $file_artists[$i] . $file_titles[$i]; } @@ -279,16 +279,27 @@ FLASH; $script = <<<SCRIPT <script type='text/javascript'> //<![CDATA[ - jQuery(document).on( 'ready as-script-load', function($) { - if ( typeof window.audioshortcode != 'undefined' ) { + (function() { + var prep = function() { + if ( 'undefined' === typeof window.audioshortcode ) { return; } audioshortcode.prep( '{$post->ID}_{$ap_playerID}', $script_files, $script_titles, $volume, - $script_loop ); + $script_loop + ); + }; + if ( 'undefined' === typeof jQuery ) { + if ( document.addEventListener ) { + window.addEventListener( 'load', prep, false ); + } else if ( document.attachEvent ) { + window.attachEvent( 'onload', prep ); + } + } else { + jQuery(document).on( 'ready as-script-load', prep ); } - } ); + })(); //]]> </script> SCRIPT; @@ -297,7 +308,7 @@ SCRIPT; if ( 0 < $num_good && ! is_feed() ) { $audio_tags .= $script; } - + return "<span style='text-align:left;display:block;'><p>$audio_tags</p></span>"; } @@ -305,11 +316,11 @@ SCRIPT; * If the theme uses infinite scroll, include jquery at the start */ function check_infinite() { - if ( current_theme_supports( 'infinite-scroll' ) ) { + if ( current_theme_supports( 'infinite-scroll' ) && class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::archive_supports_infinity() ) wp_enqueue_script( 'jquery' ); - } } + /** * Dynamically load the .js, if needed * @@ -331,8 +342,8 @@ SCRIPT; wp_as_js.type = 'text/javascript'; wp_as_js.src = $script_url; wp_as_js.async = true; - wp_as_js.onload = function() { - jQuery( document.body ).trigger( 'as-script-load' ); + wp_as_js.onload = function() { + jQuery( document.body ).trigger( 'as-script-load' ); }; document.getElementsByTagName( 'head' )[0].appendChild( wp_as_js ); } else { diff --git a/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css b/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css new file mode 100644 index 00000000..167ec706 --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/css/rtl/slideshow-shortcode-rtl.css @@ -0,0 +1,131 @@ +/* This file was automatically generated on Jan 06 2013 05:39:50 */ + +.slideshow-window { + background-color: #222; + border: 20px solid #222; + border-radius: 11px; + -moz-border-radius: 11px; + -webkit-border-radius: 11px; + -khtml-border-radius: 11px; + margin-bottom: 20px; +} + +.slideshow-window, .slideshow-window * { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +.slideshow-loading { + height: 100%; + text-align: center; + margin: auto; +} + +body div.slideshow-window * img { + /* Override any styles that might be present in the page stylesheet */ + border-width: 0 !important; + padding: 0 !important; + background-color: transparent !important; + background-image: none !important; + max-width: 100%; +} + +.slideshow-loading img { + vertical-align: middle; +} + +.slideshow-slide { + height: 100%; + width: 100%; + text-align: center; + margin: auto; + display: none; +} + +.slideshow-slide img { + vertical-align: middle; +} + +.slideshow-line-height-hack { + overflow: hide; + width: 0px; + font-size: 0px; +} + +.slideshow-slide-caption { + font-size: 13px; + font-family: "Helvetica Neue", sans-serif; + color: #f7f7f7; + text-shadow: #222 2px 1px 1px; + line-height: 25px; + height: 25px; + position: absolute; + bottom: 5px; + right: 0; + z-index: 100; + width: 100%; + text-align: center; +} + +/* @noflip */ +.slideshow-controls { + z-index: 1000; + position: absolute; + bottom: 30px; + margin: auto; + text-align: center; + width: 100%; + display: none; + direction:ltr; +} + +body div div.slideshow-controls a, +body div div.slideshow-controls a:hover { + border:2px solid rgba(255,255,255,0.1) !important; + background-color: #000 !important; + background-color: rgba(0,0,0,0.6) !important; + background-image: url('../../img/slideshow-controls.png') !important; + background-repeat: no-repeat; + background-size: 142px 16px !important; + background-position: -34px 8px !important; + color: #222 !important; + margin: 0 5px !important; + padding: 0 !important; + display: inline-block !important; + *display: inline; + zoom: 1; + height: 32px !important; + width: 32px !important; + line-height: 32px !important; + text-align: center !important; + -khtml-border-radius: 10em !important; + -webkit-border-radius: 10em !important; + -moz-border-radius: 10em !important; + border-radius: 10em !important; + -webkit-transition: 300ms border-color ease-out; + -moz-transition: 300ms border-color ease-out; + -o-transition: 300ms border-color ease-out; + transition: 300ms border-color ease-out; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 1.5) { + body div div.slideshow-controls a, + body div div.slideshow-controls a:hover { + background-image: url('../../img/slideshow-controls-2x.png') !important; + } +} + +body div div.slideshow-controls a:hover { + border-color: rgba(255,255,255,1) !important; +} + +body div div.slideshow-controls a:first-child { background-position: -76px 8px !important;} +body div div.slideshow-controls a:last-child { background-position: -117px 8px !important;} +body div div.slideshow-controls a:nth-child(2) { background-position: -34px 8px !important;} +body div div.slideshow-controls a.running { background-position: -34px 8px !important;} +body div div.slideshow-controls a.paused { background-position: 9px 8px !important;} + +.slideshow-controls a img { + border: 50px dotted fuchsia; +} diff --git a/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css b/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css new file mode 100644 index 00000000..e6d05b23 --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/css/slideshow-shortcode.css @@ -0,0 +1,129 @@ +.slideshow-window { + background-color: #222; + border: 20px solid #222; + border-radius: 11px; + -moz-border-radius: 11px; + -webkit-border-radius: 11px; + -khtml-border-radius: 11px; + margin-bottom: 20px; +} + +.slideshow-window, .slideshow-window * { + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; +} + +.slideshow-loading { + height: 100%; + text-align: center; + margin: auto; +} + +body div.slideshow-window * img { + /* Override any styles that might be present in the page stylesheet */ + border-width: 0 !important; + padding: 0 !important; + background-color: transparent !important; + background-image: none !important; + max-width: 100%; +} + +.slideshow-loading img { + vertical-align: middle; +} + +.slideshow-slide { + height: 100%; + width: 100%; + text-align: center; + margin: auto; + display: none; +} + +.slideshow-slide img { + vertical-align: middle; +} + +.slideshow-line-height-hack { + overflow: hide; + width: 0px; + font-size: 0px; +} + +.slideshow-slide-caption { + font-size: 13px; + font-family: "Helvetica Neue", sans-serif; + color: #f7f7f7; + text-shadow: #222 1px 1px 2px; + line-height: 25px; + height: 25px; + position: absolute; + bottom: 5px; + left: 0; + z-index: 100; + width: 100%; + text-align: center; +} + +/* @noflip */ +.slideshow-controls { + z-index: 1000; + position: absolute; + bottom: 30px; + margin: auto; + text-align: center; + width: 100%; + display: none; + direction:ltr; +} + +body div div.slideshow-controls a, +body div div.slideshow-controls a:hover { + border:2px solid rgba(255,255,255,0.1) !important; + background-color: #000 !important; + background-color: rgba(0,0,0,0.6) !important; + background-image: url('../img/slideshow-controls.png') !important; + background-repeat: no-repeat; + background-size: 142px 16px !important; + background-position: -34px 8px !important; + color: #222 !important; + margin: 0 5px !important; + padding: 0 !important; + display: inline-block !important; + *display: inline; + zoom: 1; + height: 32px !important; + width: 32px !important; + line-height: 32px !important; + text-align: center !important; + -khtml-border-radius: 10em !important; + -webkit-border-radius: 10em !important; + -moz-border-radius: 10em !important; + border-radius: 10em !important; + -webkit-transition: 300ms border-color ease-out; + -moz-transition: 300ms border-color ease-out; + -o-transition: 300ms border-color ease-out; + transition: 300ms border-color ease-out; +} + +@media only screen and (-webkit-min-device-pixel-ratio: 1.5) { + body div div.slideshow-controls a, + body div div.slideshow-controls a:hover { + background-image: url('../img/slideshow-controls-2x.png') !important; + } +} + +body div div.slideshow-controls a:hover { + border-color: rgba(255,255,255,1) !important; +} + +body div div.slideshow-controls a:first-child { background-position: -76px 8px !important;} +body div div.slideshow-controls a:last-child { background-position: -117px 8px !important;} +body div div.slideshow-controls a:nth-child(2) { background-position: -34px 8px !important;} +body div div.slideshow-controls a.running { background-position: -34px 8px !important;} +body div div.slideshow-controls a.paused { background-position: 9px 8px !important;} + +.slideshow-controls a img { + border: 50px dotted fuchsia; +} diff --git a/plugins/jetpack/modules/shortcodes/googlemaps.php b/plugins/jetpack/modules/shortcodes/googlemaps.php index 8ced50ea..fe79a9e6 100644 --- a/plugins/jetpack/modules/shortcodes/googlemaps.php +++ b/plugins/jetpack/modules/shortcodes/googlemaps.php @@ -77,7 +77,7 @@ function jetpack_googlemaps_shortcode( $atts ) { $url = substr( $url, 0, -5 ); $link_url = preg_replace( '!output=embed!', 'source=embed', $url ); - return '<iframe width="' . $width . '" height="' . $height . '" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="' . $url . '"></iframe><br /><small><a href="' . $link_url . '" style="text-align:left">View Larger Map</a></small>'; + return '<div class="googlemaps"><iframe width="' . $width . '" height="' . $height . '" frameborder="0" scrolling="no" marginheight="0" marginwidth="0" src="' . $url . '"></iframe><br /><small><a href="' . $link_url . '" style="text-align:left">View Larger Map</a></small></div>'; } } add_shortcode( 'googlemaps', 'jetpack_googlemaps_shortcode' ); diff --git a/plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.png b/plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.png Binary files differnew file mode 100644 index 00000000..2c76ac05 --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/img/slideshow-controls-2x.png diff --git a/plugins/jetpack/modules/shortcodes/img/slideshow-controls.png b/plugins/jetpack/modules/shortcodes/img/slideshow-controls.png Binary files differnew file mode 100644 index 00000000..09ca4871 --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/img/slideshow-controls.png diff --git a/plugins/jetpack/modules/shortcodes/img/slideshow-loader.gif b/plugins/jetpack/modules/shortcodes/img/slideshow-loader.gif Binary files differnew file mode 100644 index 00000000..ce1c594e --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/img/slideshow-loader.gif diff --git a/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js b/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js new file mode 100644 index 00000000..7697258e --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/js/audio-shortcode.js @@ -0,0 +1,154 @@ +(function($) { + +window.audioshortcode = { + + /** + * Prep the audio player once the page is ready, add listeners, etc + */ + prep: function( player_id, files, titles, volume, loop ) { + // check if the player has already been prepped, no-op if it has + var container = $( '#wp-as-' + player_id + '-container' ); + if ( container.hasClass( 'wp-as-prepped' ) ) { + return; + } + container.addClass( 'wp-as-prepped' ); + + // browser doesn't support HTML5 audio, no-op + if ( ! document.createElement('audio').canPlayType ) { + return; + } + + // if the browser removed the script, no-op + player = $( '#wp-as-' + player_id ).get(0); + if ( typeof player === 'undefined' ) { + return; + } + + this[player_id] = []; + this[player_id].i = 0; + this[player_id].files = files; + this[player_id].titles = titles; + player.volume = volume; + + var type_map = { + 'mp3': 'mpeg', + 'wav': 'wav', + 'ogg': 'ogg', + 'oga': 'ogg', + 'm4a': 'mp4', + 'aac': 'mp4', + 'webm': 'webm' + }; + + // strip out all the files that can't be played + for ( var i = this[player_id].files.length-1; i >= 0; i-- ) { + var extension = this[player_id].files[i].split( '.' ).pop(); + var type = 'audio/' + type_map[extension]; + if ( ! player.canPlayType( type ) ) { + this.remove_track( player_id, i ); + } + } + + // bail if there are no more good files + if ( 0 == this[player_id].files.length ) { + return; + } + player.src = this[player_id].files[0]; + + // show the controls if there are still 2+ files remaining + if ( 1 < this[player_id].files.length ) { + $( '#wp-as-' + player_id + '-controls' ).show(); + } + + player.addEventListener( 'error', function() { + audioshortcode.remove_track( player_id, audioshortcode[player_id].i ); + if ( 0 < audioshortcode[player_id].files.length ) { + audioshortcode[player_id].i--; + audioshortcode.next_track( player_id, false, loop ); + } + }, false ); + + player.addEventListener( 'ended', function() { + audioshortcode.next_track( player_id, false, loop ); + }, false ); + + player.addEventListener( 'play', function() { + var i = audioshortcode[player_id].i; + var titles = audioshortcode[player_id].titles; + $( '#wp-as-' + player_id + '-playing' ).text( ' ' + titles[i] ); + }, false ); + + player.addEventListener( 'pause', function() { + $( '#wp-as-' + player_id + '-playing' ).text( '' ); + }, false ); + }, + + /** + * Remove the track and update the player/controls if needed + */ + remove_track: function( player_id, index ) { + this[player_id].files.splice( index, 1 ); + this[player_id].titles.splice( index, 1 ); + + // get rid of player/controls if they can't be played + if ( 0 == this[player_id].files.length ) { + $( '#wp-as-' + player_id + '-container' ).html( $( '#wp-as-' + player_id + '-nope' ).html() ); + $( '#wp-as-' + player_id + '-controls' ).html( '' ); + } else if ( 1 == this[player_id].files.length ) { + $( '#wp-as-' + player_id + '-controls' ).html( '' ); + } + }, + + /** + * Change the src of the player, load the file, then play it + */ + start_track: function( player_id, file ) { + var player = $( '#wp-as-' + player_id ).get(0); + player.src = file; + player.load(); + player.play(); + }, + + /** + * Play the previous track + */ + prev_track: function( player_id ) { + var player = $( '#wp-as-' + player_id ).get(0); + var files = this[player_id].files; + if ( player.paused || 0 == this[player_id].i ) { + return + }; + + player.pause(); + if ( 0 < this[player_id].i ) { + this[player_id].i--; + this.start_track( player_id, files[this[player_id].i] ); + } + }, + + /** + * Play the next track + */ + next_track: function( player_id, fromClick, loop ) { + var player = $( '#wp-as-' + player_id ).get(0); + var files = this[player_id].files; + if ( fromClick && ( player.paused || files.length-1 == this[player_id].i ) ) { + return; + } + + player.pause(); + if ( files.length-1 > this[player_id].i ) { + this[player_id].i++; + this.start_track( player_id, files[this[player_id].i] ); + } else if ( loop ) { + this[player_id].i = 0; + this.start_track( player_id, 0 ); + } else { + this[player_id].i = 0; + player.src = files[0]; + $( '#wp-as-' + player_id + '-playing' ).text( '' ); + } + } +}; + +})(jQuery); diff --git a/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js b/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js new file mode 100644 index 00000000..89d583eb --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/js/jquery.cycle.js @@ -0,0 +1,1551 @@ +/*! + * jQuery Cycle Plugin (with Transition Definitions) + * Examples and documentation at: http://jquery.malsup.com/cycle/ + * Copyright (c) 2007-2010 M. Alsup + * Version: 2.9999.8 (26-OCT-2012) + * Dual licensed under the MIT and GPL licenses. + * http://jquery.malsup.com/license.html + * Requires: jQuery v1.3.2 or later + */ +;(function($, undefined) { +"use strict"; + +var ver = '2.9999.8'; + +// if $.support is not defined (pre jQuery 1.3) add what I need +if ($.support === undefined) { + $.support = { + opacity: !($.browser.msie) + }; +} + +function debug(s) { + if ($.fn.cycle.debug) + log(s); +} +function log() { + if (window.console && console.log) + console.log('[cycle] ' + Array.prototype.join.call(arguments,' ')); +} +$.expr[':'].paused = function(el) { + return el.cyclePause; +}; + + +// the options arg can be... +// a number - indicates an immediate transition should occur to the given slide index +// a string - 'pause', 'resume', 'toggle', 'next', 'prev', 'stop', 'destroy' or the name of a transition effect (ie, 'fade', 'zoom', etc) +// an object - properties to control the slideshow +// +// the arg2 arg can be... +// the name of an fx (only used in conjunction with a numeric value for 'options') +// the value true (only used in first arg == 'resume') and indicates +// that the resume should occur immediately (not wait for next timeout) + +$.fn.cycle = function(options, arg2) { + var o = { s: this.selector, c: this.context }; + + // in 1.3+ we can fix mistakes with the ready state + if (this.length === 0 && options != 'stop') { + if (!$.isReady && o.s) { + log('DOM not ready, queuing slideshow'); + $(function() { + $(o.s,o.c).cycle(options,arg2); + }); + return this; + } + // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready() + log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)')); + return this; + } + + // iterate the matched nodeset + return this.each(function() { + var opts = handleArguments(this, options, arg2); + if (opts === false) + return; + + opts.updateActivePagerLink = opts.updateActivePagerLink || $.fn.cycle.updateActivePagerLink; + + // stop existing slideshow for this container (if there is one) + if (this.cycleTimeout) + clearTimeout(this.cycleTimeout); + this.cycleTimeout = this.cyclePause = 0; + this.cycleStop = 0; // issue #108 + + var $cont = $(this); + var $slides = opts.slideExpr ? $(opts.slideExpr, this) : $cont.children(); + var els = $slides.get(); + + if (els.length < 2) { + log('terminating; too few slides: ' + els.length); + return; + } + + var opts2 = buildOptions($cont, $slides, els, opts, o); + if (opts2 === false) + return; + + var startTime = opts2.continuous ? 10 : getTimeout(els[opts2.currSlide], els[opts2.nextSlide], opts2, !opts2.backwards); + + // if it's an auto slideshow, kick it off + if (startTime) { + startTime += (opts2.delay || 0); + if (startTime < 10) + startTime = 10; + debug('first timeout: ' + startTime); + this.cycleTimeout = setTimeout(function(){go(els,opts2,0,!opts.backwards);}, startTime); + } + }); +}; + +function triggerPause(cont, byHover, onPager) { + var opts = $(cont).data('cycle.opts'); + if (!opts) + return; + var paused = !!cont.cyclePause; + if (paused && opts.paused) + opts.paused(cont, opts, byHover, onPager); + else if (!paused && opts.resumed) + opts.resumed(cont, opts, byHover, onPager); +} + +// process the args that were passed to the plugin fn +function handleArguments(cont, options, arg2) { + if (cont.cycleStop === undefined) + cont.cycleStop = 0; + if (options === undefined || options === null) + options = {}; + if (options.constructor == String) { + switch(options) { + case 'destroy': + case 'stop': + var opts = $(cont).data('cycle.opts'); + if (!opts) + return false; + cont.cycleStop++; // callbacks look for change + if (cont.cycleTimeout) + clearTimeout(cont.cycleTimeout); + cont.cycleTimeout = 0; + if (opts.elements) + $(opts.elements).stop(); + $(cont).removeData('cycle.opts'); + if (options == 'destroy') + destroy(cont, opts); + return false; + case 'toggle': + cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1; + checkInstantResume(cont.cyclePause, arg2, cont); + triggerPause(cont); + return false; + case 'pause': + cont.cyclePause = 1; + triggerPause(cont); + return false; + case 'resume': + cont.cyclePause = 0; + checkInstantResume(false, arg2, cont); + triggerPause(cont); + return false; + case 'prev': + case 'next': + opts = $(cont).data('cycle.opts'); + if (!opts) { + log('options not found, "prev/next" ignored'); + return false; + } + $.fn.cycle[options](opts); + return false; + default: + options = { fx: options }; + } + return options; + } + else if (options.constructor == Number) { + // go to the requested slide + var num = options; + options = $(cont).data('cycle.opts'); + if (!options) { + log('options not found, can not advance slide'); + return false; + } + if (num < 0 || num >= options.elements.length) { + log('invalid slide index: ' + num); + return false; + } + options.nextSlide = num; + if (cont.cycleTimeout) { + clearTimeout(cont.cycleTimeout); + cont.cycleTimeout = 0; + } + if (typeof arg2 == 'string') + options.oneTimeFx = arg2; + go(options.elements, options, 1, num >= options.currSlide); + return false; + } + return options; + + function checkInstantResume(isPaused, arg2, cont) { + if (!isPaused && arg2 === true) { // resume now! + var options = $(cont).data('cycle.opts'); + if (!options) { + log('options not found, can not resume'); + return false; + } + if (cont.cycleTimeout) { + clearTimeout(cont.cycleTimeout); + cont.cycleTimeout = 0; + } + go(options.elements, options, 1, !options.backwards); + } + } +} + +function removeFilter(el, opts) { + if (!$.support.opacity && opts.cleartype && el.style.filter) { + try { el.style.removeAttribute('filter'); } + catch(smother) {} // handle old opera versions + } +} + +// unbind event handlers +function destroy(cont, opts) { + if (opts.next) + $(opts.next).unbind(opts.prevNextEvent); + if (opts.prev) + $(opts.prev).unbind(opts.prevNextEvent); + + if (opts.pager || opts.pagerAnchorBuilder) + $.each(opts.pagerAnchors || [], function() { + this.unbind().remove(); + }); + opts.pagerAnchors = null; + $(cont).unbind('mouseenter.cycle mouseleave.cycle'); + if (opts.destroy) // callback + opts.destroy(opts); +} + +// one-time initialization +function buildOptions($cont, $slides, els, options, o) { + var startingSlideSpecified; + // support metadata plugin (v1.0 and v2.0) + var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {}); + var meta = $.isFunction($cont.data) ? $cont.data(opts.metaAttr) : null; + if (meta) + opts = $.extend(opts, meta); + if (opts.autostop) + opts.countdown = opts.autostopCount || els.length; + + var cont = $cont[0]; + $cont.data('cycle.opts', opts); + opts.$cont = $cont; + opts.stopCount = cont.cycleStop; + opts.elements = els; + opts.before = opts.before ? [opts.before] : []; + opts.after = opts.after ? [opts.after] : []; + + // push some after callbacks + if (!$.support.opacity && opts.cleartype) + opts.after.push(function() { removeFilter(this, opts); }); + if (opts.continuous) + opts.after.push(function() { go(els,opts,0,!opts.backwards); }); + + saveOriginalOpts(opts); + + // clearType corrections + if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg) + clearTypeFix($slides); + + // container requires non-static position so that slides can be position within + if ($cont.css('position') == 'static') + $cont.css('position', 'relative'); + if (opts.width) + $cont.width(opts.width); + if (opts.height && opts.height != 'auto') + $cont.height(opts.height); + + if (opts.startingSlide !== undefined) { + opts.startingSlide = parseInt(opts.startingSlide,10); + if (opts.startingSlide >= els.length || opts.startSlide < 0) + opts.startingSlide = 0; // catch bogus input + else + startingSlideSpecified = true; + } + else if (opts.backwards) + opts.startingSlide = els.length - 1; + else + opts.startingSlide = 0; + + // if random, mix up the slide array + if (opts.random) { + opts.randomMap = []; + for (var i = 0; i < els.length; i++) + opts.randomMap.push(i); + opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;}); + if (startingSlideSpecified) { + // try to find the specified starting slide and if found set start slide index in the map accordingly + for ( var cnt = 0; cnt < els.length; cnt++ ) { + if ( opts.startingSlide == opts.randomMap[cnt] ) { + opts.randomIndex = cnt; + } + } + } + else { + opts.randomIndex = 1; + opts.startingSlide = opts.randomMap[1]; + } + } + else if (opts.startingSlide >= els.length) + opts.startingSlide = 0; // catch bogus input + opts.currSlide = opts.startingSlide || 0; + var first = opts.startingSlide; + + // set position and zIndex on all the slides + $slides.css({position: 'absolute', top:0, left:0}).hide().each(function(i) { + var z; + if (opts.backwards) + z = first ? i <= first ? els.length + (i-first) : first-i : els.length-i; + else + z = first ? i >= first ? els.length - (i-first) : first-i : els.length-i; + $(this).css('z-index', z); + }); + + // make sure first slide is visible + $(els[first]).css('opacity',1).show(); // opacity bit needed to handle restart use case + removeFilter(els[first], opts); + + // stretch slides + if (opts.fit) { + if (!opts.aspect) { + if (opts.width) + $slides.width(opts.width); + if (opts.height && opts.height != 'auto') + $slides.height(opts.height); + } else { + $slides.each(function(){ + var $slide = $(this); + var ratio = (opts.aspect === true) ? $slide.width()/$slide.height() : opts.aspect; + if( opts.width && $slide.width() != opts.width ) { + $slide.width( opts.width ); + $slide.height( opts.width / ratio ); + } + + if( opts.height && $slide.height() < opts.height ) { + $slide.height( opts.height ); + $slide.width( opts.height * ratio ); + } + }); + } + } + + if (opts.center && ((!opts.fit) || opts.aspect)) { + $slides.each(function(){ + var $slide = $(this); + $slide.css({ + "margin-left": opts.width ? + ((opts.width - $slide.width()) / 2) + "px" : + 0, + "margin-top": opts.height ? + ((opts.height - $slide.height()) / 2) + "px" : + 0 + }); + }); + } + + if (opts.center && !opts.fit && !opts.slideResize) { + $slides.each(function(){ + var $slide = $(this); + $slide.css({ + "margin-left": opts.width ? ((opts.width - $slide.width()) / 2) + "px" : 0, + "margin-top": opts.height ? ((opts.height - $slide.height()) / 2) + "px" : 0 + }); + }); + } + + // stretch container + var reshape = (opts.containerResize || opts.containerResizeHeight) && !$cont.innerHeight(); + if (reshape) { // do this only if container has no size http://tinyurl.com/da2oa9 + var maxw = 0, maxh = 0; + for(var j=0; j < els.length; j++) { + var $e = $(els[j]), e = $e[0], w = $e.outerWidth(), h = $e.outerHeight(); + if (!w) w = e.offsetWidth || e.width || $e.attr('width'); + if (!h) h = e.offsetHeight || e.height || $e.attr('height'); + maxw = w > maxw ? w : maxw; + maxh = h > maxh ? h : maxh; + } + if (opts.containerResize && maxw > 0 && maxh > 0) + $cont.css({width:maxw+'px',height:maxh+'px'}); + if (opts.containerResizeHeight && maxh > 0) + $cont.css({height:maxh+'px'}); + } + + var pauseFlag = false; // https://github.com/malsup/cycle/issues/44 + if (opts.pause) + $cont.bind('mouseenter.cycle', function(){ + pauseFlag = true; + this.cyclePause++; + triggerPause(cont, true); + }).bind('mouseleave.cycle', function(){ + if (pauseFlag) + this.cyclePause--; + triggerPause(cont, true); + }); + + if (supportMultiTransitions(opts) === false) + return false; + + // apparently a lot of people use image slideshows without height/width attributes on the images. + // Cycle 2.50+ requires the sizing info for every slide; this block tries to deal with that. + var requeue = false; + options.requeueAttempts = options.requeueAttempts || 0; + $slides.each(function() { + // try to get height/width of each slide + var $el = $(this); + this.cycleH = (opts.fit && opts.height) ? opts.height : ($el.height() || this.offsetHeight || this.height || $el.attr('height') || 0); + this.cycleW = (opts.fit && opts.width) ? opts.width : ($el.width() || this.offsetWidth || this.width || $el.attr('width') || 0); + + if ( $el.is('img') ) { + // sigh.. sniffing, hacking, shrugging... this crappy hack tries to account for what browsers do when + // an image is being downloaded and the markup did not include sizing info (height/width attributes); + // there seems to be some "default" sizes used in this situation + var loadingIE = ($.browser.msie && this.cycleW == 28 && this.cycleH == 30 && !this.complete); + var loadingFF = ($.browser.mozilla && this.cycleW == 34 && this.cycleH == 19 && !this.complete); + var loadingOp = ($.browser.opera && ((this.cycleW == 42 && this.cycleH == 19) || (this.cycleW == 37 && this.cycleH == 17)) && !this.complete); + var loadingOther = (this.cycleH === 0 && this.cycleW === 0 && !this.complete); + // don't requeue for images that are still loading but have a valid size + if (loadingIE || loadingFF || loadingOp || loadingOther) { + if (o.s && opts.requeueOnImageNotLoaded && ++options.requeueAttempts < 100) { // track retry count so we don't loop forever + log(options.requeueAttempts,' - img slide not loaded, requeuing slideshow: ', this.src, this.cycleW, this.cycleH); + setTimeout(function() {$(o.s,o.c).cycle(options);}, opts.requeueTimeout); + requeue = true; + return false; // break each loop + } + else { + log('could not determine size of image: '+this.src, this.cycleW, this.cycleH); + } + } + } + return true; + }); + + if (requeue) + return false; + + opts.cssBefore = opts.cssBefore || {}; + opts.cssAfter = opts.cssAfter || {}; + opts.cssFirst = opts.cssFirst || {}; + opts.animIn = opts.animIn || {}; + opts.animOut = opts.animOut || {}; + + $slides.not(':eq('+first+')').css(opts.cssBefore); + $($slides[first]).css(opts.cssFirst); + + if (opts.timeout) { + opts.timeout = parseInt(opts.timeout,10); + // ensure that timeout and speed settings are sane + if (opts.speed.constructor == String) + opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed,10); + if (!opts.sync) + opts.speed = opts.speed / 2; + + var buffer = opts.fx == 'none' ? 0 : opts.fx == 'shuffle' ? 500 : 250; + while((opts.timeout - opts.speed) < buffer) // sanitize timeout + opts.timeout += opts.speed; + } + if (opts.easing) + opts.easeIn = opts.easeOut = opts.easing; + if (!opts.speedIn) + opts.speedIn = opts.speed; + if (!opts.speedOut) + opts.speedOut = opts.speed; + + opts.slideCount = els.length; + opts.currSlide = opts.lastSlide = first; + if (opts.random) { + if (++opts.randomIndex == els.length) + opts.randomIndex = 0; + opts.nextSlide = opts.randomMap[opts.randomIndex]; + } + else if (opts.backwards) + opts.nextSlide = opts.startingSlide === 0 ? (els.length-1) : opts.startingSlide-1; + else + opts.nextSlide = opts.startingSlide >= (els.length-1) ? 0 : opts.startingSlide+1; + + // run transition init fn + if (!opts.multiFx) { + var init = $.fn.cycle.transitions[opts.fx]; + if ($.isFunction(init)) + init($cont, $slides, opts); + else if (opts.fx != 'custom' && !opts.multiFx) { + log('unknown transition: ' + opts.fx,'; slideshow terminating'); + return false; + } + } + + // fire artificial events + var e0 = $slides[first]; + if (!opts.skipInitializationCallbacks) { + if (opts.before.length) + opts.before[0].apply(e0, [e0, e0, opts, true]); + if (opts.after.length) + opts.after[0].apply(e0, [e0, e0, opts, true]); + } + if (opts.next) + $(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,1);}); + if (opts.prev) + $(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,0);}); + if (opts.pager || opts.pagerAnchorBuilder) + buildPager(els,opts); + + exposeAddSlide(opts, els); + + return opts; +} + +// save off original opts so we can restore after clearing state +function saveOriginalOpts(opts) { + opts.original = { before: [], after: [] }; + opts.original.cssBefore = $.extend({}, opts.cssBefore); + opts.original.cssAfter = $.extend({}, opts.cssAfter); + opts.original.animIn = $.extend({}, opts.animIn); + opts.original.animOut = $.extend({}, opts.animOut); + $.each(opts.before, function() { opts.original.before.push(this); }); + $.each(opts.after, function() { opts.original.after.push(this); }); +} + +function supportMultiTransitions(opts) { + var i, tx, txs = $.fn.cycle.transitions; + // look for multiple effects + if (opts.fx.indexOf(',') > 0) { + opts.multiFx = true; + opts.fxs = opts.fx.replace(/\s*/g,'').split(','); + // discard any bogus effect names + for (i=0; i < opts.fxs.length; i++) { + var fx = opts.fxs[i]; + tx = txs[fx]; + if (!tx || !txs.hasOwnProperty(fx) || !$.isFunction(tx)) { + log('discarding unknown transition: ',fx); + opts.fxs.splice(i,1); + i--; + } + } + // if we have an empty list then we threw everything away! + if (!opts.fxs.length) { + log('No valid transitions named; slideshow terminating.'); + return false; + } + } + else if (opts.fx == 'all') { // auto-gen the list of transitions + opts.multiFx = true; + opts.fxs = []; + for (var p in txs) { + if (txs.hasOwnProperty(p)) { + tx = txs[p]; + if (txs.hasOwnProperty(p) && $.isFunction(tx)) + opts.fxs.push(p); + } + } + } + if (opts.multiFx && opts.randomizeEffects) { + // munge the fxs array to make effect selection random + var r1 = Math.floor(Math.random() * 20) + 30; + for (i = 0; i < r1; i++) { + var r2 = Math.floor(Math.random() * opts.fxs.length); + opts.fxs.push(opts.fxs.splice(r2,1)[0]); + } + debug('randomized fx sequence: ',opts.fxs); + } + return true; +} + +// provide a mechanism for adding slides after the slideshow has started +function exposeAddSlide(opts, els) { + opts.addSlide = function(newSlide, prepend) { + var $s = $(newSlide), s = $s[0]; + if (!opts.autostopCount) + opts.countdown++; + els[prepend?'unshift':'push'](s); + if (opts.els) + opts.els[prepend?'unshift':'push'](s); // shuffle needs this + opts.slideCount = els.length; + + // add the slide to the random map and resort + if (opts.random) { + opts.randomMap.push(opts.slideCount-1); + opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;}); + } + + $s.css('position','absolute'); + $s[prepend?'prependTo':'appendTo'](opts.$cont); + + if (prepend) { + opts.currSlide++; + opts.nextSlide++; + } + + if (!$.support.opacity && opts.cleartype && !opts.cleartypeNoBg) + clearTypeFix($s); + + if (opts.fit && opts.width) + $s.width(opts.width); + if (opts.fit && opts.height && opts.height != 'auto') + $s.height(opts.height); + s.cycleH = (opts.fit && opts.height) ? opts.height : $s.height(); + s.cycleW = (opts.fit && opts.width) ? opts.width : $s.width(); + + $s.css(opts.cssBefore); + + if (opts.pager || opts.pagerAnchorBuilder) + $.fn.cycle.createPagerAnchor(els.length-1, s, $(opts.pager), els, opts); + + if ($.isFunction(opts.onAddSlide)) + opts.onAddSlide($s); + else + $s.hide(); // default behavior + }; +} + +// reset internal state; we do this on every pass in order to support multiple effects +$.fn.cycle.resetState = function(opts, fx) { + fx = fx || opts.fx; + opts.before = []; opts.after = []; + opts.cssBefore = $.extend({}, opts.original.cssBefore); + opts.cssAfter = $.extend({}, opts.original.cssAfter); + opts.animIn = $.extend({}, opts.original.animIn); + opts.animOut = $.extend({}, opts.original.animOut); + opts.fxFn = null; + $.each(opts.original.before, function() { opts.before.push(this); }); + $.each(opts.original.after, function() { opts.after.push(this); }); + + // re-init + var init = $.fn.cycle.transitions[fx]; + if ($.isFunction(init)) + init(opts.$cont, $(opts.elements), opts); +}; + +// this is the main engine fn, it handles the timeouts, callbacks and slide index mgmt +function go(els, opts, manual, fwd) { + var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide]; + + // opts.busy is true if we're in the middle of an animation + if (manual && opts.busy && opts.manualTrump) { + // let manual transitions requests trump active ones + debug('manualTrump in go(), stopping active transition'); + $(els).stop(true,true); + opts.busy = 0; + clearTimeout(p.cycleTimeout); + } + + // don't begin another timeout-based transition if there is one active + if (opts.busy) { + debug('transition active, ignoring new tx request'); + return; + } + + + // stop cycling if we have an outstanding stop request + if (p.cycleStop != opts.stopCount || p.cycleTimeout === 0 && !manual) + return; + + // check to see if we should stop cycling based on autostop options + if (!manual && !p.cyclePause && !opts.bounce && + ((opts.autostop && (--opts.countdown <= 0)) || + (opts.nowrap && !opts.random && opts.nextSlide < opts.currSlide))) { + if (opts.end) + opts.end(opts); + return; + } + + // if slideshow is paused, only transition on a manual trigger + var changed = false; + if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) { + changed = true; + var fx = opts.fx; + // keep trying to get the slide size if we don't have it yet + curr.cycleH = curr.cycleH || $(curr).height(); + curr.cycleW = curr.cycleW || $(curr).width(); + next.cycleH = next.cycleH || $(next).height(); + next.cycleW = next.cycleW || $(next).width(); + + // support multiple transition types + if (opts.multiFx) { + if (fwd && (opts.lastFx === undefined || ++opts.lastFx >= opts.fxs.length)) + opts.lastFx = 0; + else if (!fwd && (opts.lastFx === undefined || --opts.lastFx < 0)) + opts.lastFx = opts.fxs.length - 1; + fx = opts.fxs[opts.lastFx]; + } + + // one-time fx overrides apply to: $('div').cycle(3,'zoom'); + if (opts.oneTimeFx) { + fx = opts.oneTimeFx; + opts.oneTimeFx = null; + } + + $.fn.cycle.resetState(opts, fx); + + // run the before callbacks + if (opts.before.length) + $.each(opts.before, function(i,o) { + if (p.cycleStop != opts.stopCount) return; + o.apply(next, [curr, next, opts, fwd]); + }); + + // stage the after callacks + var after = function() { + opts.busy = 0; + $.each(opts.after, function(i,o) { + if (p.cycleStop != opts.stopCount) return; + o.apply(next, [curr, next, opts, fwd]); + }); + if (!p.cycleStop) { + // queue next transition + queueNext(); + } + }; + + debug('tx firing('+fx+'); currSlide: ' + opts.currSlide + '; nextSlide: ' + opts.nextSlide); + + // get ready to perform the transition + opts.busy = 1; + if (opts.fxFn) // fx function provided? + opts.fxFn(curr, next, opts, after, fwd, manual && opts.fastOnEvent); + else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ? + $.fn.cycle[opts.fx](curr, next, opts, after, fwd, manual && opts.fastOnEvent); + else + $.fn.cycle.custom(curr, next, opts, after, fwd, manual && opts.fastOnEvent); + } + else { + queueNext(); + } + + if (changed || opts.nextSlide == opts.currSlide) { + // calculate the next slide + var roll; + opts.lastSlide = opts.currSlide; + if (opts.random) { + opts.currSlide = opts.nextSlide; + if (++opts.randomIndex == els.length) { + opts.randomIndex = 0; + opts.randomMap.sort(function(a,b) {return Math.random() - 0.5;}); + } + opts.nextSlide = opts.randomMap[opts.randomIndex]; + if (opts.nextSlide == opts.currSlide) + opts.nextSlide = (opts.currSlide == opts.slideCount - 1) ? 0 : opts.currSlide + 1; + } + else if (opts.backwards) { + roll = (opts.nextSlide - 1) < 0; + if (roll && opts.bounce) { + opts.backwards = !opts.backwards; + opts.nextSlide = 1; + opts.currSlide = 0; + } + else { + opts.nextSlide = roll ? (els.length-1) : opts.nextSlide-1; + opts.currSlide = roll ? 0 : opts.nextSlide+1; + } + } + else { // sequence + roll = (opts.nextSlide + 1) == els.length; + if (roll && opts.bounce) { + opts.backwards = !opts.backwards; + opts.nextSlide = els.length-2; + opts.currSlide = els.length-1; + } + else { + opts.nextSlide = roll ? 0 : opts.nextSlide+1; + opts.currSlide = roll ? els.length-1 : opts.nextSlide-1; + } + } + } + if (changed && opts.pager) + opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass); + + function queueNext() { + // stage the next transition + var ms = 0, timeout = opts.timeout; + if (opts.timeout && !opts.continuous) { + ms = getTimeout(els[opts.currSlide], els[opts.nextSlide], opts, fwd); + if (opts.fx == 'shuffle') + ms -= opts.speedOut; + } + else if (opts.continuous && p.cyclePause) // continuous shows work off an after callback, not this timer logic + ms = 10; + if (ms > 0) + p.cycleTimeout = setTimeout(function(){ go(els, opts, 0, !opts.backwards); }, ms); + } +} + +// invoked after transition +$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) { + $(pager).each(function() { + $(this).children().removeClass(clsName).eq(currSlide).addClass(clsName); + }); +}; + +// calculate timeout value for current transition +function getTimeout(curr, next, opts, fwd) { + if (opts.timeoutFn) { + // call user provided calc fn + var t = opts.timeoutFn.call(curr,curr,next,opts,fwd); + while (opts.fx != 'none' && (t - opts.speed) < 250) // sanitize timeout + t += opts.speed; + debug('calculated timeout: ' + t + '; speed: ' + opts.speed); + if (t !== false) + return t; + } + return opts.timeout; +} + +// expose next/prev function, caller must pass in state +$.fn.cycle.next = function(opts) { advance(opts,1); }; +$.fn.cycle.prev = function(opts) { advance(opts,0);}; + +// advance slide forward or back +function advance(opts, moveForward) { + var val = moveForward ? 1 : -1; + var els = opts.elements; + var p = opts.$cont[0], timeout = p.cycleTimeout; + if (timeout) { + clearTimeout(timeout); + p.cycleTimeout = 0; + } + if (opts.random && val < 0) { + // move back to the previously display slide + opts.randomIndex--; + if (--opts.randomIndex == -2) + opts.randomIndex = els.length-2; + else if (opts.randomIndex == -1) + opts.randomIndex = els.length-1; + opts.nextSlide = opts.randomMap[opts.randomIndex]; + } + else if (opts.random) { + opts.nextSlide = opts.randomMap[opts.randomIndex]; + } + else { + opts.nextSlide = opts.currSlide + val; + if (opts.nextSlide < 0) { + if (opts.nowrap) return false; + opts.nextSlide = els.length - 1; + } + else if (opts.nextSlide >= els.length) { + if (opts.nowrap) return false; + opts.nextSlide = 0; + } + } + + var cb = opts.onPrevNextEvent || opts.prevNextClick; // prevNextClick is deprecated + if ($.isFunction(cb)) + cb(val > 0, opts.nextSlide, els[opts.nextSlide]); + go(els, opts, 1, moveForward); + return false; +} + +function buildPager(els, opts) { + var $p = $(opts.pager); + $.each(els, function(i,o) { + $.fn.cycle.createPagerAnchor(i,o,$p,els,opts); + }); + opts.updateActivePagerLink(opts.pager, opts.startingSlide, opts.activePagerClass); +} + +$.fn.cycle.createPagerAnchor = function(i, el, $p, els, opts) { + var a; + if ($.isFunction(opts.pagerAnchorBuilder)) { + a = opts.pagerAnchorBuilder(i,el); + debug('pagerAnchorBuilder('+i+', el) returned: ' + a); + } + else + a = '<a href="#">'+(i+1)+'</a>'; + + if (!a) + return; + var $a = $(a); + // don't reparent if anchor is in the dom + if ($a.parents('body').length === 0) { + var arr = []; + if ($p.length > 1) { + $p.each(function() { + var $clone = $a.clone(true); + $(this).append($clone); + arr.push($clone[0]); + }); + $a = $(arr); + } + else { + $a.appendTo($p); + } + } + + opts.pagerAnchors = opts.pagerAnchors || []; + opts.pagerAnchors.push($a); + + var pagerFn = function(e) { + e.preventDefault(); + opts.nextSlide = i; + var p = opts.$cont[0], timeout = p.cycleTimeout; + if (timeout) { + clearTimeout(timeout); + p.cycleTimeout = 0; + } + var cb = opts.onPagerEvent || opts.pagerClick; // pagerClick is deprecated + if ($.isFunction(cb)) + cb(opts.nextSlide, els[opts.nextSlide]); + go(els,opts,1,opts.currSlide < i); // trigger the trans +// return false; // <== allow bubble + }; + + if ( /mouseenter|mouseover/i.test(opts.pagerEvent) ) { + $a.hover(pagerFn, function(){/* no-op */} ); + } + else { + $a.bind(opts.pagerEvent, pagerFn); + } + + if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble) + $a.bind('click.cycle', function(){return false;}); // suppress click + + var cont = opts.$cont[0]; + var pauseFlag = false; // https://github.com/malsup/cycle/issues/44 + if (opts.pauseOnPagerHover) { + $a.hover( + function() { + pauseFlag = true; + cont.cyclePause++; + triggerPause(cont,true,true); + }, function() { + if (pauseFlag) + cont.cyclePause--; + triggerPause(cont,true,true); + } + ); + } +}; + +// helper fn to calculate the number of slides between the current and the next +$.fn.cycle.hopsFromLast = function(opts, fwd) { + var hops, l = opts.lastSlide, c = opts.currSlide; + if (fwd) + hops = c > l ? c - l : opts.slideCount - l; + else + hops = c < l ? l - c : l + opts.slideCount - c; + return hops; +}; + +// fix clearType problems in ie6 by setting an explicit bg color +// (otherwise text slides look horrible during a fade transition) +function clearTypeFix($slides) { + debug('applying clearType background-color hack'); + function hex(s) { + s = parseInt(s,10).toString(16); + return s.length < 2 ? '0'+s : s; + } + function getBg(e) { + for ( ; e && e.nodeName.toLowerCase() != 'html'; e = e.parentNode) { + var v = $.css(e,'background-color'); + if (v && v.indexOf('rgb') >= 0 ) { + var rgb = v.match(/\d+/g); + return '#'+ hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]); + } + if (v && v != 'transparent') + return v; + } + return '#ffffff'; + } + $slides.each(function() { $(this).css('background-color', getBg(this)); }); +} + +// reset common props before the next transition +$.fn.cycle.commonReset = function(curr,next,opts,w,h,rev) { + $(opts.elements).not(curr).hide(); + if (typeof opts.cssBefore.opacity == 'undefined') + opts.cssBefore.opacity = 1; + opts.cssBefore.display = 'block'; + if (opts.slideResize && w !== false && next.cycleW > 0) + opts.cssBefore.width = next.cycleW; + if (opts.slideResize && h !== false && next.cycleH > 0) + opts.cssBefore.height = next.cycleH; + opts.cssAfter = opts.cssAfter || {}; + opts.cssAfter.display = 'none'; + $(curr).css('zIndex',opts.slideCount + (rev === true ? 1 : 0)); + $(next).css('zIndex',opts.slideCount + (rev === true ? 0 : 1)); +}; + +// the actual fn for effecting a transition +$.fn.cycle.custom = function(curr, next, opts, cb, fwd, speedOverride) { + var $l = $(curr), $n = $(next); + var speedIn = opts.speedIn, speedOut = opts.speedOut, easeIn = opts.easeIn, easeOut = opts.easeOut; + $n.css(opts.cssBefore); + if (speedOverride) { + if (typeof speedOverride == 'number') + speedIn = speedOut = speedOverride; + else + speedIn = speedOut = 1; + easeIn = easeOut = null; + } + var fn = function() { + $n.animate(opts.animIn, speedIn, easeIn, function() { + cb(); + }); + }; + $l.animate(opts.animOut, speedOut, easeOut, function() { + $l.css(opts.cssAfter); + if (!opts.sync) + fn(); + }); + if (opts.sync) fn(); +}; + +// transition definitions - only fade is defined here, transition pack defines the rest +$.fn.cycle.transitions = { + fade: function($cont, $slides, opts) { + $slides.not(':eq('+opts.currSlide+')').css('opacity',0); + opts.before.push(function(curr,next,opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.cssBefore.opacity = 0; + }); + opts.animIn = { opacity: 1 }; + opts.animOut = { opacity: 0 }; + opts.cssBefore = { top: 0, left: 0 }; + } +}; + +$.fn.cycle.ver = function() { return ver; }; + +// override these globally if you like (they are all optional) +$.fn.cycle.defaults = { + activePagerClass: 'activeSlide', // class name used for the active pager link + after: null, // transition callback (scope set to element that was shown): function(currSlideElement, nextSlideElement, options, forwardFlag) + allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling + animIn: null, // properties that define how the slide animates in + animOut: null, // properties that define how the slide animates out + aspect: false, // preserve aspect ratio during fit resizing, cropping if necessary (must be used with fit option) + autostop: 0, // true to end slideshow after X transitions (where X == slide count) + autostopCount: 0, // number of transitions (optionally used with autostop to define X) + backwards: false, // true to start slideshow at last slide and move backwards through the stack + before: null, // transition callback (scope set to element to be shown): function(currSlideElement, nextSlideElement, options, forwardFlag) + center: null, // set to true to have cycle add top/left margin to each slide (use with width and height options) + cleartype: !$.support.opacity, // true if clearType corrections should be applied (for IE) + cleartypeNoBg: false, // set to true to disable extra cleartype fixing (leave false to force background color setting on slides) + containerResize: 1, // resize container to fit largest slide + containerResizeHeight: 0, // resize containers height to fit the largest slide but leave the width dynamic + continuous: 0, // true to start next transition immediately after current one completes + cssAfter: null, // properties that defined the state of the slide after transitioning out + cssBefore: null, // properties that define the initial state of the slide before transitioning in + delay: 0, // additional delay (in ms) for first transition (hint: can be negative) + easeIn: null, // easing for "in" transition + easeOut: null, // easing for "out" transition + easing: null, // easing method for both in and out transitions + end: null, // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options) + fastOnEvent: 0, // force fast transitions when triggered manually (via pager or prev/next); value == time in ms + fit: 0, // force slides to fit container + fx: 'fade', // name of transition effect (or comma separated names, ex: 'fade,scrollUp,shuffle') + fxFn: null, // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag) + height: 'auto', // container height (if the 'fit' option is true, the slides will be set to this height as well) + manualTrump: true, // causes manual transition to stop an active transition instead of being ignored + metaAttr: 'cycle', // data- attribute that holds the option data for the slideshow + next: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for next slide + nowrap: 0, // true to prevent slideshow from wrapping + onPagerEvent: null, // callback fn for pager events: function(zeroBasedSlideIndex, slideElement) + onPrevNextEvent: null, // callback fn for prev/next events: function(isNext, zeroBasedSlideIndex, slideElement) + pager: null, // element, jQuery object, or jQuery selector string for the element to use as pager container + pagerAnchorBuilder: null, // callback fn for building anchor links: function(index, DOMelement) + pagerEvent: 'click.cycle', // name of event which drives the pager navigation + pause: 0, // true to enable "pause on hover" + pauseOnPagerHover: 0, // true to pause when hovering over pager link + prev: null, // element, jQuery object, or jQuery selector string for the element to use as event trigger for previous slide + prevNextEvent: 'click.cycle',// event which drives the manual transition to the previous or next slide + random: 0, // true for random, false for sequence (not applicable to shuffle fx) + randomizeEffects: 1, // valid when multiple effects are used; true to make the effect sequence random + requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded + requeueTimeout: 250, // ms delay for requeue + rev: 0, // causes animations to transition in reverse (for effects that support it such as scrollHorz/scrollVert/shuffle) + shuffle: null, // coords for shuffle animation, ex: { top:15, left: 200 } + skipInitializationCallbacks: false, // set to true to disable the first before/after callback that occurs prior to any transition + slideExpr: null, // expression for selecting slides (if something other than all children is required) + slideResize: 1, // force slide width/height to fixed size before every transition + speed: 1000, // speed of the transition (any valid fx speed value) + speedIn: null, // speed of the 'in' transition + speedOut: null, // speed of the 'out' transition + startingSlide: undefined,// zero-based index of the first slide to be displayed + sync: 1, // true if in/out transitions should occur simultaneously + timeout: 4000, // milliseconds between slide transitions (0 to disable auto advance) + timeoutFn: null, // callback for determining per-slide timeout value: function(currSlideElement, nextSlideElement, options, forwardFlag) + updateActivePagerLink: null,// callback fn invoked to update the active pager link (adds/removes activePagerClass style) + width: null // container width (if the 'fit' option is true, the slides will be set to this width as well) +}; + +})(jQuery); + + +/*! + * jQuery Cycle Plugin Transition Definitions + * This script is a plugin for the jQuery Cycle Plugin + * Examples and documentation at: http://malsup.com/jquery/cycle/ + * Copyright (c) 2007-2010 M. Alsup + * Version: 2.73 + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +(function($) { +"use strict"; + +// +// These functions define slide initialization and properties for the named +// transitions. To save file size feel free to remove any of these that you +// don't need. +// +$.fn.cycle.transitions.none = function($cont, $slides, opts) { + opts.fxFn = function(curr,next,opts,after){ + $(next).show(); + $(curr).hide(); + after(); + }; +}; + +// not a cross-fade, fadeout only fades out the top slide +$.fn.cycle.transitions.fadeout = function($cont, $slides, opts) { + $slides.not(':eq('+opts.currSlide+')').css({ display: 'block', 'opacity': 1 }); + opts.before.push(function(curr,next,opts,w,h,rev) { + $(curr).css('zIndex',opts.slideCount + (rev !== true ? 1 : 0)); + $(next).css('zIndex',opts.slideCount + (rev !== true ? 0 : 1)); + }); + opts.animIn.opacity = 1; + opts.animOut.opacity = 0; + opts.cssBefore.opacity = 1; + opts.cssBefore.display = 'block'; + opts.cssAfter.zIndex = 0; +}; + +// scrollUp/Down/Left/Right +$.fn.cycle.transitions.scrollUp = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var h = $cont.height(); + opts.cssBefore.top = h; + opts.cssBefore.left = 0; + opts.cssFirst.top = 0; + opts.animIn.top = 0; + opts.animOut.top = -h; +}; +$.fn.cycle.transitions.scrollDown = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var h = $cont.height(); + opts.cssFirst.top = 0; + opts.cssBefore.top = -h; + opts.cssBefore.left = 0; + opts.animIn.top = 0; + opts.animOut.top = h; +}; +$.fn.cycle.transitions.scrollLeft = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var w = $cont.width(); + opts.cssFirst.left = 0; + opts.cssBefore.left = w; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.left = 0-w; +}; +$.fn.cycle.transitions.scrollRight = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push($.fn.cycle.commonReset); + var w = $cont.width(); + opts.cssFirst.left = 0; + opts.cssBefore.left = -w; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.left = w; +}; +$.fn.cycle.transitions.scrollHorz = function($cont, $slides, opts) { + $cont.css('overflow','hidden').width(); + opts.before.push(function(curr, next, opts, fwd) { + if (opts.rev) + fwd = !fwd; + $.fn.cycle.commonReset(curr,next,opts); + opts.cssBefore.left = fwd ? (next.cycleW-1) : (1-next.cycleW); + opts.animOut.left = fwd ? -curr.cycleW : curr.cycleW; + }); + opts.cssFirst.left = 0; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.top = 0; +}; +$.fn.cycle.transitions.scrollVert = function($cont, $slides, opts) { + $cont.css('overflow','hidden'); + opts.before.push(function(curr, next, opts, fwd) { + if (opts.rev) + fwd = !fwd; + $.fn.cycle.commonReset(curr,next,opts); + opts.cssBefore.top = fwd ? (1-next.cycleH) : (next.cycleH-1); + opts.animOut.top = fwd ? curr.cycleH : -curr.cycleH; + }); + opts.cssFirst.top = 0; + opts.cssBefore.left = 0; + opts.animIn.top = 0; + opts.animOut.left = 0; +}; + +// slideX/slideY +$.fn.cycle.transitions.slideX = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $(opts.elements).not(curr).hide(); + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.animIn.width = next.cycleW; + }); + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; + opts.animIn.width = 'show'; + opts.animOut.width = 0; +}; +$.fn.cycle.transitions.slideY = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $(opts.elements).not(curr).hide(); + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.animIn.height = next.cycleH; + }); + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.cssBefore.height = 0; + opts.animIn.height = 'show'; + opts.animOut.height = 0; +}; + +// shuffle +$.fn.cycle.transitions.shuffle = function($cont, $slides, opts) { + var i, w = $cont.css('overflow', 'visible').width(); + $slides.css({left: 0, top: 0}); + opts.before.push(function(curr,next,opts) { + $.fn.cycle.commonReset(curr,next,opts,true,true,true); + }); + // only adjust speed once! + if (!opts.speedAdjusted) { + opts.speed = opts.speed / 2; // shuffle has 2 transitions + opts.speedAdjusted = true; + } + opts.random = 0; + opts.shuffle = opts.shuffle || {left:-w, top:15}; + opts.els = []; + for (i=0; i < $slides.length; i++) + opts.els.push($slides[i]); + + for (i=0; i < opts.currSlide; i++) + opts.els.push(opts.els.shift()); + + // custom transition fn (hat tip to Benjamin Sterling for this bit of sweetness!) + opts.fxFn = function(curr, next, opts, cb, fwd) { + if (opts.rev) + fwd = !fwd; + var $el = fwd ? $(curr) : $(next); + $(next).css(opts.cssBefore); + var count = opts.slideCount; + $el.animate(opts.shuffle, opts.speedIn, opts.easeIn, function() { + var hops = $.fn.cycle.hopsFromLast(opts, fwd); + for (var k=0; k < hops; k++) { + if (fwd) + opts.els.push(opts.els.shift()); + else + opts.els.unshift(opts.els.pop()); + } + if (fwd) { + for (var i=0, len=opts.els.length; i < len; i++) + $(opts.els[i]).css('z-index', len-i+count); + } + else { + var z = $(curr).css('z-index'); + $el.css('z-index', parseInt(z,10)+1+count); + } + $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() { + $(fwd ? this : curr).hide(); + if (cb) cb(); + }); + }); + }; + $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 }); +}; + +// turnUp/Down/Left/Right +$.fn.cycle.transitions.turnUp = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.cssBefore.top = next.cycleH; + opts.animIn.height = next.cycleH; + opts.animOut.width = next.cycleW; + }); + opts.cssFirst.top = 0; + opts.cssBefore.left = 0; + opts.cssBefore.height = 0; + opts.animIn.top = 0; + opts.animOut.height = 0; +}; +$.fn.cycle.transitions.turnDown = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH; + }); + opts.cssFirst.top = 0; + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.cssBefore.height = 0; + opts.animOut.height = 0; +}; +$.fn.cycle.transitions.turnLeft = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.cssBefore.left = next.cycleW; + opts.animIn.width = next.cycleW; + }); + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; + opts.animIn.left = 0; + opts.animOut.width = 0; +}; +$.fn.cycle.transitions.turnRight = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.animIn.width = next.cycleW; + opts.animOut.left = curr.cycleW; + }); + $.extend(opts.cssBefore, { top: 0, left: 0, width: 0 }); + opts.animIn.left = 0; + opts.animOut.width = 0; +}; + +// zoom +$.fn.cycle.transitions.zoom = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,false,true); + opts.cssBefore.top = next.cycleH/2; + opts.cssBefore.left = next.cycleW/2; + $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH }); + $.extend(opts.animOut, { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 }); + }); + opts.cssFirst.top = 0; + opts.cssFirst.left = 0; + opts.cssBefore.width = 0; + opts.cssBefore.height = 0; +}; + +// fadeZoom +$.fn.cycle.transitions.fadeZoom = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,false); + opts.cssBefore.left = next.cycleW/2; + opts.cssBefore.top = next.cycleH/2; + $.extend(opts.animIn, { top: 0, left: 0, width: next.cycleW, height: next.cycleH }); + }); + opts.cssBefore.width = 0; + opts.cssBefore.height = 0; + opts.animOut.opacity = 0; +}; + +// blindX +$.fn.cycle.transitions.blindX = function($cont, $slides, opts) { + var w = $cont.css('overflow','hidden').width(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.animIn.width = next.cycleW; + opts.animOut.left = curr.cycleW; + }); + opts.cssBefore.left = w; + opts.cssBefore.top = 0; + opts.animIn.left = 0; + opts.animOut.left = w; +}; +// blindY +$.fn.cycle.transitions.blindY = function($cont, $slides, opts) { + var h = $cont.css('overflow','hidden').height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH; + }); + opts.cssBefore.top = h; + opts.cssBefore.left = 0; + opts.animIn.top = 0; + opts.animOut.top = h; +}; +// blindZ +$.fn.cycle.transitions.blindZ = function($cont, $slides, opts) { + var h = $cont.css('overflow','hidden').height(); + var w = $cont.width(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH; + }); + opts.cssBefore.top = h; + opts.cssBefore.left = w; + opts.animIn.top = 0; + opts.animIn.left = 0; + opts.animOut.top = h; + opts.animOut.left = w; +}; + +// growX - grow horizontally from centered 0 width +$.fn.cycle.transitions.growX = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true); + opts.cssBefore.left = this.cycleW/2; + opts.animIn.left = 0; + opts.animIn.width = this.cycleW; + opts.animOut.left = 0; + }); + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; +}; +// growY - grow vertically from centered 0 height +$.fn.cycle.transitions.growY = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false); + opts.cssBefore.top = this.cycleH/2; + opts.animIn.top = 0; + opts.animIn.height = this.cycleH; + opts.animOut.top = 0; + }); + opts.cssBefore.height = 0; + opts.cssBefore.left = 0; +}; + +// curtainX - squeeze in both edges horizontally +$.fn.cycle.transitions.curtainX = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,false,true,true); + opts.cssBefore.left = next.cycleW/2; + opts.animIn.left = 0; + opts.animIn.width = this.cycleW; + opts.animOut.left = curr.cycleW/2; + opts.animOut.width = 0; + }); + opts.cssBefore.top = 0; + opts.cssBefore.width = 0; +}; +// curtainY - squeeze in both edges vertically +$.fn.cycle.transitions.curtainY = function($cont, $slides, opts) { + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,false,true); + opts.cssBefore.top = next.cycleH/2; + opts.animIn.top = 0; + opts.animIn.height = next.cycleH; + opts.animOut.top = curr.cycleH/2; + opts.animOut.height = 0; + }); + opts.cssBefore.height = 0; + opts.cssBefore.left = 0; +}; + +// cover - curr slide covered by next slide +$.fn.cycle.transitions.cover = function($cont, $slides, opts) { + var d = opts.direction || 'left'; + var w = $cont.css('overflow','hidden').width(); + var h = $cont.height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts); + opts.cssAfter.display = ''; + if (d == 'right') + opts.cssBefore.left = -w; + else if (d == 'up') + opts.cssBefore.top = h; + else if (d == 'down') + opts.cssBefore.top = -h; + else + opts.cssBefore.left = w; + }); + opts.animIn.left = 0; + opts.animIn.top = 0; + opts.cssBefore.top = 0; + opts.cssBefore.left = 0; +}; + +// uncover - curr slide moves off next slide +$.fn.cycle.transitions.uncover = function($cont, $slides, opts) { + var d = opts.direction || 'left'; + var w = $cont.css('overflow','hidden').width(); + var h = $cont.height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,true,true); + if (d == 'right') + opts.animOut.left = w; + else if (d == 'up') + opts.animOut.top = -h; + else if (d == 'down') + opts.animOut.top = h; + else + opts.animOut.left = -w; + }); + opts.animIn.left = 0; + opts.animIn.top = 0; + opts.cssBefore.top = 0; + opts.cssBefore.left = 0; +}; + +// toss - move top slide and fade away +$.fn.cycle.transitions.toss = function($cont, $slides, opts) { + var w = $cont.css('overflow','visible').width(); + var h = $cont.height(); + opts.before.push(function(curr, next, opts) { + $.fn.cycle.commonReset(curr,next,opts,true,true,true); + // provide default toss settings if animOut not provided + if (!opts.animOut.left && !opts.animOut.top) + $.extend(opts.animOut, { left: w*2, top: -h/2, opacity: 0 }); + else + opts.animOut.opacity = 0; + }); + opts.cssBefore.left = 0; + opts.cssBefore.top = 0; + opts.animIn.left = 0; +}; + +// wipe - clip animation +$.fn.cycle.transitions.wipe = function($cont, $slides, opts) { + var w = $cont.css('overflow','hidden').width(); + var h = $cont.height(); + opts.cssBefore = opts.cssBefore || {}; + var clip; + if (opts.clip) { + if (/l2r/.test(opts.clip)) + clip = 'rect(0px 0px '+h+'px 0px)'; + else if (/r2l/.test(opts.clip)) + clip = 'rect(0px '+w+'px '+h+'px '+w+'px)'; + else if (/t2b/.test(opts.clip)) + clip = 'rect(0px '+w+'px 0px 0px)'; + else if (/b2t/.test(opts.clip)) + clip = 'rect('+h+'px '+w+'px '+h+'px 0px)'; + else if (/zoom/.test(opts.clip)) { + var top = parseInt(h/2,10); + var left = parseInt(w/2,10); + clip = 'rect('+top+'px '+left+'px '+top+'px '+left+'px)'; + } + } + + opts.cssBefore.clip = opts.cssBefore.clip || clip || 'rect(0px 0px 0px 0px)'; + + var d = opts.cssBefore.clip.match(/(\d+)/g); + var t = parseInt(d[0],10), r = parseInt(d[1],10), b = parseInt(d[2],10), l = parseInt(d[3],10); + + opts.before.push(function(curr, next, opts) { + if (curr == next) return; + var $curr = $(curr), $next = $(next); + $.fn.cycle.commonReset(curr,next,opts,true,true,false); + opts.cssAfter.display = 'block'; + + var step = 1, count = parseInt((opts.speedIn / 13),10) - 1; + (function f() { + var tt = t ? t - parseInt(step * (t/count),10) : 0; + var ll = l ? l - parseInt(step * (l/count),10) : 0; + var bb = b < h ? b + parseInt(step * ((h-b)/count || 1),10) : h; + var rr = r < w ? r + parseInt(step * ((w-r)/count || 1),10) : w; + $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' }); + (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none'); + })(); + }); + $.extend(opts.cssBefore, { display: 'block', opacity: 1, top: 0, left: 0 }); + opts.animIn = { left: 0 }; + opts.animOut = { left: 0 }; +}; + +})(jQuery); diff --git a/plugins/jetpack/modules/shortcodes/js/slideshow-shortcode.js b/plugins/jetpack/modules/shortcodes/js/slideshow-shortcode.js new file mode 100644 index 00000000..5e132097 --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/js/slideshow-shortcode.js @@ -0,0 +1,187 @@ +function JetpackSlideshow( element, width, height, transition ) { + this.element = element; + this.images = []; + this.controls = {}; + this.transition = transition || 'fade'; + + var currentWidth = this.element.width(); + if ( !width || width > currentWidth ) + width = currentWidth; + + this.width = width; + this.height = height; + this.element.css( { + 'height': this.height + 'px' + } ); +} + +JetpackSlideshow.prototype.showLoadingImage = function( toggle ) { + if ( toggle ) { + this.loadingImage_ = document.createElement( 'div' ); + this.loadingImage_.className = 'slideshow-loading'; + var img = document.createElement( 'img' ); + img.src = jetpackSlideshowSettings.spinner; + this.loadingImage_.appendChild( img ); + this.loadingImage_.appendChild( this.makeZeroWidthSpan() ); + this.loadingImage_.style.lineHeight = this.height + 'px'; + this.element.append( this.loadingImage_ ); + } else if ( this.loadingImage_ ) { + this.loadingImage_.parentNode.removeChild( this.loadingImage_ ); + this.loadingImage_ = null; + } +}; + +JetpackSlideshow.prototype.init = function() { + this.showLoadingImage(true); + + var self = this; + // Set up DOM. + for ( var i = 0; i < this.images.length; i++ ) { + var imageInfo = this.images[i]; + var img = document.createElement( 'img' ); + img.src = imageInfo.src + '?w=' + this.width; + img.align = 'middle'; + var caption = document.createElement( 'div' ); + caption.className = 'slideshow-slide-caption'; + caption.innerHTML = imageInfo.caption; + var container = document.createElement('div'); + container.className = 'slideshow-slide'; + container.style.lineHeight = this.height + 'px'; + + // Hide loading image once first image has loaded. + if ( i == 0 ) { + if ( img.complete ) { + // IE, image in cache + setTimeout( function() { + self.finishInit_(); + }, 1); + } else { + jQuery( img ).load(function() { + self.finishInit_(); + }); + } + } + container.appendChild( img ); + // I'm not sure where these were coming from, but IE adds + // bad values for width/height for portrait-mode images + img.removeAttribute('width'); + img.removeAttribute('height'); + container.appendChild( this.makeZeroWidthSpan() ); + container.appendChild( caption ); + this.element.append( container ); + } +}; + +JetpackSlideshow.prototype.makeZeroWidthSpan = function() { + var emptySpan = document.createElement( 'span' ); + emptySpan.className = 'slideshow-line-height-hack'; + // Having a NBSP makes IE act weird during transitions, but other + // browsers ignore a text node with a space in it as whitespace. + if (jQuery.browser.msie) { + emptySpan.appendChild( document.createTextNode(' ') ); + } else { + emptySpan.innerHTML = ' '; + } + return emptySpan; +}; + +JetpackSlideshow.prototype.finishInit_ = function() { + this.showLoadingImage( false ); + this.renderControls_(); + + var self = this; + // Initialize Cycle instance. + this.element.cycle( { + fx: this.transition, + prev: this.controls.prev, + next: this.controls.next, + slideExpr: '.slideshow-slide', + onPrevNextEvent: function() { + return self.onCyclePrevNextClick_.apply( self, arguments ); + } + } ); + + var slideshow = this.element; + jQuery( this.controls['stop'] ).click( function() { + var button = jQuery(this); + if ( ! button.hasClass( 'paused' ) ) { + slideshow.cycle( 'pause' ); + button.removeClass( 'running' ); + button.addClass( 'paused' ); + } else { + button.addClass( 'running' ); + button.removeClass( 'paused' ); + slideshow.cycle( 'resume', true ); + } + return false; + } ); + + var controls = jQuery( this.controlsDiv_ ); + slideshow.mouseenter( function() { + controls.fadeIn(); + } ); + slideshow.mouseleave( function() { + controls.fadeOut(); + } ); + + this.initialized_ = true; +}; + +JetpackSlideshow.prototype.renderControls_ = function() { + if ( this.controlsDiv_ ) + return; + + var controlsDiv = document.createElement( 'div' ); + controlsDiv.className = 'slideshow-controls'; + + controls = [ 'prev', 'stop', 'next' ]; + for ( var i = 0; i < controls.length; i++ ) { + var controlName = controls[i]; + var a = document.createElement( 'a' ); + a.href = '#'; + controlsDiv.appendChild( a ); + this.controls[controlName] = a; + } + this.element.append( controlsDiv ); + this.controlsDiv_ = controlsDiv; +}; + +JetpackSlideshow.prototype.onCyclePrevNextClick_ = function( isNext, i, slideElement ) { + // If blog_id not present don't track page views + if ( ! jetpackSlideshowSettings.blog_id ) + return; + + var postid = this.images[i].id; + var stats = new Image(); + stats.src = document.location.protocol + + '//stats.wordpress.com/g.gif?host=' + + escape( document.location.host ) + + '&rand=' + Math.random() + + '&blog=' + jetpackSlideshowSettings.blog_id + + '&subd=' + jetpackSlideshowSettings.blog_subdomain + + '&user_id=' + jetpackSlideshowSettings.user_id + + '&post=' + postid + + '&ref=' + escape( document.location ); +}; + +( function ( $ ) { + function jetpack_slideshow_init() { + $( '.jetpack-slideshow-noscript' ).remove(); + + $( '.jetpack-slideshow' ).each( function () { + var container = $( this ); + + if ( container.data( 'processed' ) ) + return; + + var slideshow = new JetpackSlideshow( container, container.data( 'width' ), container.data( 'height' ), container.data( 'trans' ) ); + slideshow.images = container.data( 'gallery' ); + slideshow.init(); + + container.data( 'processed', true ); + } ); + } + + $( document ).ready( jetpack_slideshow_init ); + $( 'body' ).on( 'post-load', jetpack_slideshow_init ); +} )( jQuery );
\ No newline at end of file diff --git a/plugins/jetpack/modules/shortcodes/polldaddy.php b/plugins/jetpack/modules/shortcodes/polldaddy.php index bcb30f81..7eb30edf 100644 --- a/plugins/jetpack/modules/shortcodes/polldaddy.php +++ b/plugins/jetpack/modules/shortcodes/polldaddy.php @@ -193,7 +193,7 @@ SCRIPT; $data = esc_attr( json_encode( $data ) ); return <<<CONTAINER -<a name="pd_a_{$poll}"></a> +<a id="pd_a_{$poll}"></a> <div class="PDS_Poll" id="PDI_container{$poll}" data-settings="{$data}" style="display:inline-block;{$float}{$margins}"></div> <div id="PD_superContainer"></div> <noscript>{$poll_link}</noscript> @@ -204,7 +204,7 @@ CONTAINER; $cb = ''; return <<<CONTAINER -<a name="pd_a_{$poll}"></a> +<a id="pd_a_{$poll}"></a> <div class="PDS_Poll" id="PDI_container{$poll}" style="display:inline-block;{$float}{$margins}"></div> <div id="PD_superContainer"></div> <script type="text/javascript" charset="UTF-8" src="{$poll_js}{$cb}"></script> @@ -395,4 +395,4 @@ if ( !function_exists( 'polldaddy_link' ) ) { add_filter( 'comment_text', 'polldaddy_link', 1 ); } -}
\ No newline at end of file +} diff --git a/plugins/jetpack/modules/shortcodes/slideshow.php b/plugins/jetpack/modules/shortcodes/slideshow.php new file mode 100644 index 00000000..ab1145d8 --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/slideshow.php @@ -0,0 +1,208 @@ +<?php + +/** + * Slideshow shortcode usage: [gallery type="slideshow"] or the older [slideshow] + */ +class Jetpack_Slideshow_Shortcode { + public $instance_count = 0; + + function __construct() { + global $shortcode_tags; + + $needs_scripts = false; + + // Only if the slideshow shortcode has not already been defined. + if ( ! array_key_exists( 'slideshow', $shortcode_tags ) ) { + add_shortcode( 'slideshow', array( $this, 'shortcode_callback' ) ); + $needs_scripts = true; + } + + // Only if the gallery shortcode has not been redefined. + if ( isset( $shortcode_tags['gallery'] ) && $shortcode_tags['gallery'] == 'gallery_shortcode' ) { + add_filter( 'post_gallery', array( $this, 'post_gallery' ), 1002, 2 ); + add_filter( 'jetpack_gallery_types', array( $this, 'add_gallery_type' ), 10 ); + $needs_scripts = true; + } + + if ( $needs_scripts ) + add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ), 1 ); + } + + /** + * Responds to the [gallery] shortcode, but not an actual shortcode callback. + * + * @param $value An empty string if nothing has modified the gallery output, the output html otherwise + * @param $attr The shortcode attributes array + * + * @return string The (un)modified $value + */ + function post_gallery( $value, $attr ) { + // Bail if somebody else has done something + if ( ! empty( $value ) ) + return $value; + + // If [gallery type="slideshow"] have it behave just like [slideshow] + if ( ! empty( $attr['type'] ) && 'slideshow' == $attr['type'] ) + return $this->shortcode_callback( $attr ); + + return $value; + } + + /** + * Add the Slideshow type to gallery settings + * + * @param $types An array of types where the key is the value, and the value is the caption. + * @see Jetpack_Tiled_Gallery::media_ui_print_templates + */ + function add_gallery_type( $types = array() ) { + $types['slideshow'] = esc_html__( 'Slideshow', 'jetpack' ); + return $types; + } + + function shortcode_callback( $attr, $content = null ) { + global $post, $content_width; + + $attr = shortcode_atts( array( + 'trans' => 'fade', + 'order' => 'ASC', + 'orderby' => 'menu_order ID', + 'id' => $post->ID, + 'include' => '', + 'exclude' => '', + ), $attr ); + + if ( 'rand' == strtolower( $attr['order'] ) ) + $attr['orderby'] = 'none'; + + $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] ); + if ( ! $attr['orderby'] ) + $attr['orderby'] = 'menu_order ID'; + + // Don't restrict to the current post if include + $post_parent = ( empty( $attr['include'] ) ) ? intval( $attr['id'] ) : null; + + $attachments = get_posts( array( + 'post_status' => 'inherit', + 'post_type' => 'attachment', + 'post_mime_type' => 'image', + 'posts_per_page' => -1, + 'post_parent' => $post_parent, + 'order' => $attr['order'], + 'orderby' => $attr['orderby'], + 'include' => $attr['include'], + 'exclude' => $attr['exclude'], + ) ); + + if ( count( $attachments ) < 2 ) + return; + + $gallery_instance = sprintf( "gallery-%d-%d", $attr['id'], ++$this->instance_count ); + + $gallery = array(); + foreach ( $attachments as $attachment ) { + $attachment_image_src = wp_get_attachment_image_src( $attachment->ID, 'full' ); + $attachment_image_src = $attachment_image_src[0]; // [url, width, height] + $caption = wptexturize( strip_tags( $attachment->post_excerpt ) ); + + $gallery[] = (object) array( + 'src' => (string) esc_url_raw( $attachment_image_src ), + 'id' => (string) $attachment->ID, + 'caption' => (string) $caption, + ); + } + + $max_width = intval( get_option( 'large_size_w' ) ); + $max_height = 450; + if ( intval( $content_width ) > 0 ) + $max_width = min( intval( $content_width ), $max_width ); + + $js_attr = array( + 'gallery' => $gallery, + 'selector' => $gallery_instance, + 'width' => $max_width, + 'height' => $max_height, + 'trans' => $attr['trans'] ? $attr['trans'] : 'fade', + ); + + // Show a link to the gallery in feeds. + if ( is_feed() ) + return sprintf( '<a href="%s">%s</a>', + esc_url( get_permalink( $post->ID ) . '#' . $gallery_instance . '-slideshow' ), + esc_html__( 'Click to view slideshow.', 'jetpack' ) + ); + + return $this->slideshow_js( $js_attr ); + } + + /** + * Render the slideshow js + * + * Returns the necessary markup and js to fire a slideshow. + * + * @uses $this->enqueue_scripts() + */ + function slideshow_js( $attr ) { + // Enqueue scripts + $this->enqueue_scripts(); + + if ( $attr['width'] <= 100 ) + $attr['width'] = 450; + + if ( $attr['height'] <= 100 ) + $attr['height'] = 450; + + // 40px padding + $attr['width'] -= 40; + $attr['height'] -= 40; + + $output = ''; + + $output .= '<p class="jetpack-slideshow-noscript robots-nocontent">' . esc_html__( 'This slideshow requires JavaScript.', 'jetpack' ) . '</p>'; + $output .= '<div id="' . esc_attr( $attr['selector'] . '-slideshow' ) . '" class="slideshow-window jetpack-slideshow" data-width="' . esc_attr( $attr['width'] ) . '" data-height="' . esc_attr( $attr['height'] ) . '" data-trans="' . esc_attr( $attr['trans'] ) . '" data-gallery="' . esc_attr( json_encode( $attr['gallery'] ) ) . '"></div>'; + + $output .= " + <style> + #{$attr['selector']}-slideshow .slideshow-slide img { + max-height: " . intval( $attr['height'] ) ."px; + /* Emulate max-height in IE 6 */ + _height: expression(this.scrollHeight >= " . intval( $attr['height'] ) . " ? '" . intval( $attr['height'] ) . "px' : 'auto'); + } + </style> + "; + + return $output; + } + + /** + * Infinite Scroll needs the scripts to be present at all times + */ + function maybe_enqueue_scripts() { + if ( is_home() && current_theme_supports( 'infinite-scroll' ) ) + $this->enqueue_scripts(); + } + + /** + * Actually enqueues the scripts and styles. + */ + function enqueue_scripts() { + static $enqueued = false; + + if ( $enqueued ) + return; + + wp_enqueue_script( 'jquery-cycle', plugins_url( '/js/jquery.cycle.js', __FILE__ ) , array( 'jquery' ), '2.9999.8', true ); + wp_enqueue_script( 'jetpack-slideshow', plugins_url( '/js/slideshow-shortcode.js', __FILE__ ), array( 'jquery-cycle' ), '20121214.1', true ); + wp_enqueue_style( 'jetpack-slideshow', plugins_url( '/css/slideshow-shortcode.css', __FILE__ ) ); + + wp_localize_script( 'jetpack-slideshow', 'jetpackSlideshowSettings', apply_filters( 'jetpack_js_slideshow_settings', array( + 'spinner' => plugins_url( '/img/slideshow-loader.gif', __FILE__ ), + ) ) ); + + $enqueued = true; + } + + public static function init() { + $gallery = new Jetpack_Slideshow_Shortcode; + } +} +add_action( 'init', array( 'Jetpack_Slideshow_Shortcode', 'init' ) ); diff --git a/plugins/jetpack/modules/shortcodes/soundcloud.php b/plugins/jetpack/modules/shortcodes/soundcloud.php index 8aa35380..a7486115 100644 --- a/plugins/jetpack/modules/shortcodes/soundcloud.php +++ b/plugins/jetpack/modules/shortcodes/soundcloud.php @@ -1,60 +1,214 @@ <?php - /* Plugin Name: SoundCloud Shortcode -Plugin URI: http://www.soundcloud.com -Description: SoundCloud Shortcode. Usage in your posts: [soundcloud]http://soundcloud.com/TRACK_PERMALINK[/soundcloud] . Works also with set or group instead of track. You can provide optional parameters height/width/params like that [soundcloud height="82" params="auto_play=true"]http.... -Version: 1.1.5 -Author: Johannes Wagener <johannes@soundcloud.com> added to wpcom by tott -Author URI: http://johannes.wagener.cc - -[soundcloud url="http://api.soundcloud.com/tracks/9408008"] -<object height="81" width="100%"> <param name="movie" value="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F8781356"></param> <param name="allowscriptaccess" value="always"></param> <embed allowscriptaccess="always" height="81" src="http://player.soundcloud.com/player.swf?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F8781356" type="application/x-shockwave-flash" width="100%"></embed> </object> <span><a href="http://soundcloud.com/robokopbeats/robokop-we-move-at-midnight-preview-forthcoming-on-mwm-recordings">Robokop - We move at midnight preview ( FORTHCOMING ON MWM recordings)</a> by <a href="http://soundcloud.com/robokopbeats">Robokop</a></span> +Plugin URI: http://wordpress.org/extend/plugins/soundcloud-shortcode/ +Description: Converts SoundCloud WordPress shortcodes to a SoundCloud widget. Example: [soundcloud]http://soundcloud.com/forss/flickermood[/soundcloud] +Version: 2.3 +Author: SoundCloud Inc., simplified for Jetpack by Automattic, Inc. +Author URI: http://soundcloud.com +License: GPLv2 + +Original version: Johannes Wagener <johannes@soundcloud.com> +Options support: Tiffany Conroy <tiffany@soundcloud.com> +HTML5 & oEmbed support: Tim Bormans <tim@soundcloud.com> +*/ + +/* +A8C: Taken from http://plugins.svn.wordpress.org/soundcloud-shortcode/trunk/ +at revision 664386. + +Commenting out (instead of removing) and replacing code with custom modifs +so it's eqsy to see what differs from the standard DOTORG version. + +All custom modifs are annoted with "A8C" keyword in comment. */ -add_filter( "pre_kses", "soundcloud_reverse_shortcode" ); +/* Register oEmbed provider + -------------------------------------------------------------------------- */ + +wp_oembed_add_provider('#https?://(?:api\.)?soundcloud\.com/.*#i', 'http://soundcloud.com/oembed', true); + + +/* Register SoundCloud shortcode + -------------------------------------------------------------------------- */ + +add_shortcode("soundcloud", "soundcloud_shortcode"); + + +/** + * SoundCloud shortcode handler + * @param {string|array} $atts The attributes passed to the shortcode like [soundcloud attr1="value" /]. + * Is an empty string when no arguments are given. + * @param {string} $content The content between non-self closing [soundcloud]…[/soundcloud] tags. + * @return {string} Widget embed code HTML + */ +function soundcloud_shortcode($atts, $content = null) { + + // Custom shortcode options + $shortcode_options = array_merge(array('url' => trim($content)), is_array($atts) ? $atts : array()); + + // Turn shortcode option "param" (param=value¶m2=value) into array + $shortcode_params = array(); + if (isset($shortcode_options['params'])) { + parse_str(html_entity_decode($shortcode_options['params']), $shortcode_params); + } + $shortcode_options['params'] = $shortcode_params; + + // User preference options + $plugin_options = array_filter(array( + 'iframe' => soundcloud_get_option('player_iframe', true), + 'width' => soundcloud_get_option('player_width'), + 'height' => soundcloud_url_has_tracklist($shortcode_options['url']) ? soundcloud_get_option('player_height_multi') : soundcloud_get_option('player_height'), + 'params' => array_filter(array( + 'auto_play' => soundcloud_get_option('auto_play'), + 'show_comments' => soundcloud_get_option('show_comments'), + 'color' => soundcloud_get_option('color'), + 'theme_color' => soundcloud_get_option('theme_color'), + )), + )); + // Needs to be an array + if (!isset($plugin_options['params'])) { $plugin_options['params'] = array(); } + + // plugin options < shortcode options + $options = array_merge( + $plugin_options, + $shortcode_options + ); + + // plugin params < shortcode params + $options['params'] = array_merge( + $plugin_options['params'], + $shortcode_options['params'] + ); + + // The "url" option is required + if (!isset($options['url'])) { + return ''; + } else { + $options['url'] = trim($options['url']); + } + + // Both "width" and "height" need to be integers + if (isset($options['width']) && !preg_match('/^\d+$/', $options['width'])) { + // set to 0 so oEmbed will use the default 100% and WordPress themes will leave it alone + $options['width'] = 0; + } + if (isset($options['height']) && !preg_match('/^\d+$/', $options['height'])) { unset($options['height']); } -function soundcloud_reverse_shortcode_preg_replace_callback( $a ) { - $pattern = '/([a-zA-Z0-9\-_%=&]*)&?url=([^&]+)&?([a-zA-Z0-9\-_%&=]*)/'; - preg_match( $pattern, str_replace( "&", "&", $a[3] ), $params ); + // The "iframe" option must be true to load the iframe widget + $iframe = soundcloud_booleanize($options['iframe']) + // Default to flash widget for permalink urls (e.g. http://soundcloud.com/{username}) + // because HTML5 widget doesn’t support those yet + ? preg_match('/api.soundcloud.com/i', $options['url']) + : false; - return '[soundcloud width="' . esc_attr( $a[2] ) . '" height="' . esc_attr( $a[1] ) . '" params="' . esc_attr( $params[1] . $params[3] ) . '" url="' . urldecode( $params[2] ) . '"]'; + // Return html embed code + if ($iframe) { + return soundcloud_iframe_widget($options); + } else { + return soundcloud_flash_widget($options); + } + +} + +/** + * Plugin options getter + * @param {string|array} $option Option name + * @param {mixed} $default Default value + * @return {mixed} Option value + */ +function soundcloud_get_option($option, $default = false) { + $value = get_option('soundcloud_' . $option); + return $value === '' ? $default : $value; +} + +/** + * Booleanize a value + * @param {boolean|string} $value + * @return {boolean} + */ +function soundcloud_booleanize($value) { + return is_bool($value) ? $value : $value === 'true' ? true : false; } -function soundcloud_reverse_shortcode( $content ){ - if ( false === stripos( $content, 'http://player.soundcloud.com/player.swf' ) ) - return $content; +/** + * Decide if a url has a tracklist + * @param {string} $url + * @return {boolean} + */ +function soundcloud_url_has_tracklist($url) { + return preg_match('/^(.+?)\/(sets|groups|playlists)\/(.+?)$/', $url); +} + +/** + * Parameterize url + * @param {array} $match Matched regex + * @return {string} Parameterized url + */ +function soundcloud_oembed_params_callback($match) { + global $soundcloud_oembed_params; - $pattern = '!<object\s*height="(\d+%?)"\s*width="(\d+%?)".*?src="http://.*?soundcloud\.com/player.swf\?([^"]+)".*?</object>.*?</span>!'; - $pattern_ent = str_replace( '&#0*58;', '&#0*58;|�*58;', htmlspecialchars( $pattern, ENT_NOQUOTES ) ); + // Convert URL to array + $url = parse_url(urldecode($match[1])); + // Convert URL query to array + parse_str($url['query'], $query_array); + // Build new query string + $query = http_build_query(array_merge($query_array, $soundcloud_oembed_params)); - if ( preg_match( $pattern_ent, $content ) ) - return( preg_replace_callback( $pattern_ent, 'soundcloud_reverse_shortcode_preg_replace_callback', $content ) ); - else - return( preg_replace_callback( $pattern, 'soundcloud_reverse_shortcode_preg_replace_callback', $content ) ); + return 'src="' . $url['scheme'] . '://' . $url['host'] . $url['path'] . '?' . $query; } -add_shortcode( "soundcloud", "soundcloud_shortcode" ); - -function soundcloud_shortcode( $atts, $url = '' ) { - if ( empty( $url ) ) - extract( shortcode_atts( array( 'url' => '', 'params' => '', 'height' => '', 'width' => '100%' ), $atts ) ); - else - extract( shortcode_atts( array( 'params' => '', 'height' => '', 'width' => '100%' ), $atts ) ); - - $encoded_url = urlencode( $url ); - if ( $url = parse_url( $url ) ) { - $splitted_url = split( "/", $url['path'] ); - $media_type = $splitted_url[ count( $splitted_url ) - 2 ]; - - if ( '' == $height ){ - if ( in_array( $media_type, array( 'groups', 'sets' ) ) ) - $height = 225; - else - $height = 81; - } - $player_params = "url=$encoded_url&g=1&$params"; - - return '<object height="' . esc_attr( $height ) . '" width="' . esc_attr( $width ) . '"><param name="movie" value="' . esc_url( "http://player.soundcloud.com/player.swf?$player_params" ) . '"></param><embed height="' . esc_attr( $height ) . '" src="' . esc_url( "http://player.soundcloud.com/player.swf?$player_params" ) . '" type="application/x-shockwave-flash" width="' . esc_attr( $width ) . '"> </embed> </object>'; - } +/** + * Iframe widget embed code + * @param {array} $options Parameters + * @return {string} Iframe embed code + */ +function soundcloud_iframe_widget($options) { + + // Merge in "url" value + $options['params'] = array_merge(array( + 'url' => $options['url'] + ), $options['params']); + + // Build URL + $url = 'http://w.soundcloud.com/player?' . http_build_query($options['params']); + // Set default width if not defined + $width = isset($options['width']) && $options['width'] !== 0 ? $options['width'] : '100%'; + // Set default height if not defined + $height = isset($options['height']) && $options['height'] !== 0 ? $options['height'] : (soundcloud_url_has_tracklist($options['url']) ? '450' : '166'); + + return sprintf('<iframe width="%s" height="%s" scrolling="no" frameborder="no" src="%s"></iframe>', $width, $height, $url); } + +/** + * Legacy Flash widget embed code + * @param {array} $options Parameters + * @return {string} Flash embed code + */ +function soundcloud_flash_widget($options) { + + // Merge in "url" value + $options['params'] = array_merge(array( + 'url' => $options['url'] + ), $options['params']); + + // Build URL + $url = 'http://player.soundcloud.com/player.swf?' . http_build_query($options['params']); + // Set default width if not defined + $width = isset($options['width']) && $options['width'] !== 0 ? $options['width'] : '100%'; + // Set default height if not defined + $height = isset($options['height']) && $options['height'] !== 0 ? $options['height'] : (soundcloud_url_has_tracklist($options['url']) ? '255' : '81'); + + return preg_replace('/\s\s+/', "", sprintf('<object width="%s" height="%s"> + <param name="movie" value="%s"></param> + <param name="allowscriptaccess" value="always"></param> + <embed width="%s" height="%s" src="%s" allowscriptaccess="always" type="application/x-shockwave-flash"></embed> + </object>', $width, $height, $url, $width, $height, $url)); +} + + + +/* Settings + -------------------------------------------------------------------------- */ + +/* A8C: no user-defined options, KISS */ diff --git a/plugins/jetpack/modules/shortcodes/ted.php b/plugins/jetpack/modules/shortcodes/ted.php new file mode 100644 index 00000000..afd35961 --- /dev/null +++ b/plugins/jetpack/modules/shortcodes/ted.php @@ -0,0 +1,68 @@ +<?php +/* + * TED Player embed code + * http://www.ted.com + * + * http://www.ted.com/talks/view/id/210 + * http://www.ted.com/talks/marc_goodman_a_vision_of_crimes_in_the_future.html + * [ted id="210" lang="eng"] + * [ted id="http://www.ted.com/talks/view/id/210" lang="eng"] + * [ted id=1539 lang=fr width=560 height=315] + */ + +wp_oembed_add_provider( '!https?://(www\.)?ted.com/talks/view/id/.+!i', 'http://www.ted.com/talks/oembed.json', true ); +wp_oembed_add_provider( '!https?://(www\.)?ted.com/talks/[a-zA-Z\-\_]+\.html!i', 'http://www.ted.com/talks/oembed.json', true ); + +add_shortcode( 'ted', 'shortcode_ted' ); +function shortcode_ted( $atts, $content = '' ) { + global $wp_embed; + + $defaults = array( + 'id' => '', + 'width' => '', + 'height' => '', + 'lang' => 'eng', + ); + $atts = shortcode_atts( $defaults, $atts ); + + if ( empty( $atts['id'] ) ) + return '<!-- Missing TED ID -->'; + + if ( preg_match( "#^[\d]+$#", $atts['id'], $matches ) ) + $url = 'http://ted.com/talks/view/id/' . $matches[0]; + elseif ( preg_match( "#^https?://(www\.)?ted\.com/talks/view/id/[0-9]+$#", $atts['id'], $matches ) ) + $url = $matches[0]; + + unset( $atts['id'] ); + + $args = array(); + if ( is_numeric( $atts['width'] ) ) + $args['width'] = $atts['width']; + else if ( $embed_size_w = get_option( 'embed_size_w' ) ) + $args['width'] = $embed_size_w; + else if ( ! empty( $GLOBALS['content_width'] ) ) + $args['width'] = (int)$GLOBALS['content_width']; + else + $args['width'] = 500; + + // Default to a 16x9 aspect ratio if there's no height set + if ( is_numeric( $atts['height'] ) ) + $args['height'] = $atts['height']; + else + $args['height'] = $args['width'] * 0.5625; + + if ( ! empty( $atts['lang'] ) ) { + $args['lang'] = sanitize_key( $atts['lang'] ); + add_filter( 'oembed_fetch_url', 'ted_filter_oembed_fetch_url', 10, 3 ); + } + $retval = $wp_embed->shortcode( $args, $url ); + remove_filter( 'oembed_fetch_url', 'ted_filter_oembed_fetch_url', 10 ); + return $retval; +} + +/** + * Filter the request URL to also include the $lang parameter + */ +function ted_filter_oembed_fetch_url( $provider, $url, $args ) { + return add_query_arg( 'lang', $args['lang'], $provider ); +} diff --git a/plugins/jetpack/modules/shortcodes/videopress.php b/plugins/jetpack/modules/shortcodes/videopress.php index 912ab4cf..6aebae03 100644 --- a/plugins/jetpack/modules/shortcodes/videopress.php +++ b/plugins/jetpack/modules/shortcodes/videopress.php @@ -4,7 +4,7 @@ * @category video * @author Automattic Inc * @link http://automattic.com/wordpress-plugins/#videopress VideoPress - * @version 1.5 + * @version 1.5.4 * @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ @@ -15,8 +15,8 @@ Description: Upload new videos to <a href="http://videopress.com/">VideoPress</a Author: Automattic, Niall Kennedy, Joseph Scott, Gary Pendergast Contributor: Hailin Wu Author URI: http://automattic.com/wordpress-plugins/#videopress -Version: 1.5 -Stable tag: 1.5 +Version: 1.5.4 +Stable tag: 1.5.4 License: GPL v2 - http://www.gnu.org/licenses/old-licenses/gpl-2.0.html */ @@ -33,7 +33,7 @@ class VideoPress { * @var string * @since 1.3 */ - const version = '1.5'; + const version = '1.5.4'; /** * Minimum allowed width. We don't expect videos viewed below this width to be useful; we drop small values to help save publishers from themselves. @@ -186,7 +186,7 @@ class VideoPress { wp_enqueue_script( 'swfobject', $swfobject, false. '2.2' ); wp_enqueue_script( 'jquery', $jquery, false, '1.4.4' ); - wp_enqueue_script( 'videopress', $vpjs, array( 'jquery','swfobject' ), '1.07' ); + wp_enqueue_script( 'videopress', $vpjs, array( 'jquery','swfobject' ), '1.09' ); $this->js_loaded = true; return true; @@ -228,10 +228,24 @@ class VideoPress { 'w' => 0, 'freedom' => false, 'flashonly' => false, - 'autoplay' => false + 'autoplay' => false, + 'hd' => false ), $attr ) ); $freedom = (bool) $freedom; + /** + * Test if embedded blog prefers videos only displayed in Freedom-loving formats + */ + if ( $freedom === false && (bool) get_option( 'video_player_freedom', false ) ) + $freedom = true; + + $forcestatic = get_option( 'video_player_static', false ); + + /** + * Set the video to HD if the blog option has it enabled + */ + if ( (bool) get_option( 'video_player_high_quality', false ) ) + $hd = true; $width = absint($w); unset($w); @@ -250,7 +264,9 @@ class VideoPress { $options = array( 'freedom' => $freedom, 'force_flash' => (bool) $flashonly, - 'autoplay' => (bool) $autoplay + 'autoplay' => (bool) $autoplay, + 'forcestatic' => $forcestatic, + 'hd' => (bool) $hd ); unset( $freedom ); unset( $flashonly ); @@ -586,7 +602,6 @@ class VideoPress_Video { $url = 'https://v.wordpress.com/data/wordpress.json'; $response = wp_remote_get( $url . '?' . http_build_query( $request_params, null, '&' ), array( - 'httpversion' => '1.1', 'redirection' => 1, 'user-agent' => 'VideoPress plugin ' . VideoPress::version . '; WordPress ' . $wp_version . ' (' . home_url('/') . ')' ) ); @@ -791,12 +806,15 @@ class VideoPress_Player { $content = ''; } elseif ( is_wp_error( $this->video ) ) { $content = $this->error_message( $this->video ); - } elseif ( ( isset( $this->video->restricted_embed ) && $this->video->restricted_embed === true ) || ( isset( $this->options['force_flash'] ) && $this->options['force_flash'] === true ) ) { + } elseif ( isset( $this->options['force_flash'] ) && $this->options['force_flash'] === true ) { $content = $this->flash_object(); + } elseif ( isset( $this->video->restricted_embed ) && $this->video->restricted_embed === true ) { + if( $this->options['forcestatic'] ) + $content = $this->flash_object(); + else + $content = $this->html5_dynamic(); } elseif ( isset( $this->options['freedom'] ) && $this->options['freedom'] === true ) { $content = $this->html5_static(); - } elseif ( ! in_the_loop() ) { - $content = $this->flash_object(); } else { $content = $this->html5_dynamic(); } @@ -1029,7 +1047,8 @@ class VideoPress_Player { 'blog' => absint( $this->video->blog_id ), 'post' => absint( $this->video->post_id ), 'duration'=> absint( $this->video->duration ), - 'poster' => esc_url_raw( $this->video->poster_frame_uri, array( 'http', 'https' ) ) + 'poster' => esc_url_raw( $this->video->poster_frame_uri, array( 'http', 'https' ) ), + 'hd' => (bool) $this->options['hd'] ); if ( isset( $this->video->videos ) ) { if ( isset( $this->video->videos->mp4 ) && isset( $this->video->videos->mp4->url ) ) @@ -1046,10 +1065,7 @@ class VideoPress_Player { $guid = $this->video->guid; $guid_js = json_encode( $guid ); $html .= '<script type="text/javascript">' . PHP_EOL; - - // Only need to wait until document is ready if the JS is being loaded in the footer - if ( ! $videopress->js_loaded ) - $html .= 'jQuery(document).ready(function() {'; + $html .= 'jQuery(document).ready(function() {'; $html .= 'if ( !jQuery.VideoPress.data[' . json_encode($guid) . '] ) { jQuery.VideoPress.data[' . json_encode($guid) . '] = new Array(); }' . PHP_EOL; $html .= 'jQuery.VideoPress.data[' . json_encode( $guid ) . '][' . $videopress->shown[$guid] . ']=' . json_encode($data) . ';' . PHP_EOL; @@ -1096,8 +1112,7 @@ class VideoPress_Player { $html .= '}'; // close the jQuery(document).ready() function - if ( !$videopress->js_loaded ) - $html .= '});'; + $html .= '});'; } $html .= '</script>' . PHP_EOL; $html .= '</div>' . PHP_EOL; diff --git a/plugins/jetpack/modules/shortcodes/vimeo.php b/plugins/jetpack/modules/shortcodes/vimeo.php index 2225a5fe..02b417e1 100644 --- a/plugins/jetpack/modules/shortcodes/vimeo.php +++ b/plugins/jetpack/modules/shortcodes/vimeo.php @@ -39,14 +39,14 @@ function vimeo_shortcode( $atts ) { if ( isset( $args['w'] ) ) { $width = (int) $args['w']; - + if ( ! isset( $args['h'] ) ) { // The case where w=300 is specified without h=200, otherwise $height // will always equal the default of 300, no matter what w was set to. $height = round( ( $width / 640 ) * 360 ); } } - + if ( isset( $args['h'] ) ) { $height = (int) $args['h']; @@ -54,7 +54,7 @@ function vimeo_shortcode( $atts ) { $width = round( ( $height / 360 ) * 640 ); } } - + if ( ! $width ) $width = absint( $content_width ); @@ -71,13 +71,13 @@ function vimeo_shortcode( $atts ) { add_shortcode( 'vimeo', 'vimeo_shortcode' ); function vimeo_embed_to_shortcode( $content ) { - if ( false === stripos( $content, 'player.vimeo.com/video/' ) ) + if ( false === stripos( $content, 'player.vimeo.com/video/' ) ) return $content; $regexp = '!<iframe\s+src=[\'"]http://player\.vimeo\.com/video/(\d+)[\'"]((?:\s+\w+=[\'"][^\'"]*[\'"])*)></iframe>!i'; - $regexp_ent = str_replace( '&#0*58;', '&#0*58;|�*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) ); - - foreach ( array( 'regexp', 'regexp_ent' ) as $reg ) { + $regexp_ent = str_replace( '&#0*58;', '&#0*58;|�*58;', htmlspecialchars( $regexp, ENT_NOQUOTES ) ); + + foreach ( array( 'regexp', 'regexp_ent' ) as $reg ) { if ( !preg_match_all( $$reg, $content, $matches, PREG_SET_ORDER ) ) continue; @@ -86,7 +86,7 @@ function vimeo_embed_to_shortcode( $content ) { $params = $match[2]; - if ( 'regexp_ent' == $reg ) + if ( 'regexp_ent' == $reg ) $params = html_entity_decode( $params ); $params = wp_kses_hair( $params, array( 'http' ) ); @@ -95,8 +95,8 @@ function vimeo_embed_to_shortcode( $content ) { $height = isset( $params['height'] ) ? (int) $params['height']['value'] : 0; $wh = ''; - if ( $width && $height ) - $wh = ' w=' . $width . ' h=' . $height; + if ( $width && $height ) + $wh = ' w=' . $width . ' h=' . $height; $shortcode = '[vimeo ' . $id . $wh . ']'; $content = str_replace( $match[0], $shortcode, $content ); diff --git a/plugins/jetpack/modules/shortcodes/youtube.php b/plugins/jetpack/modules/shortcodes/youtube.php index ebf989f0..74c497ed 100644 --- a/plugins/jetpack/modules/shortcodes/youtube.php +++ b/plugins/jetpack/modules/shortcodes/youtube.php @@ -140,6 +140,7 @@ function youtube_sanitize_url( $url ) { function get_youtube_id( $url ) { $url = youtube_sanitize_url( $url ); $url = parse_url( $url ); + $id = false; if ( ! isset( $url['query'] ) ) return false; @@ -149,7 +150,8 @@ function get_youtube_id( $url ) { if ( ! isset( $qargs['v'] ) && ! isset( $qargs['list'] ) ) return false; - $id = preg_replace( '|[^_a-z0-9-]|i', '', $qargs['list'] ); + if ( isset( $qargs['list'] ) ) + $id = preg_replace( '|[^_a-z0-9-]|i', '', $qargs['list'] ); if ( empty( $id ) ) $id = preg_replace( '|[^_a-z0-9-]|i', '', $qargs['v'] ); @@ -175,12 +177,6 @@ function youtube_id( $url ) { parse_str( $url['query'], $qargs ); - $agent = $_SERVER['HTTP_USER_AGENT']; - // Bloglines & Google Reader handle YouTube well now, instead of - // big blank space of yester year, so they can skip this treatment - if ( is_feed() && ! preg_match( '#' . apply_filters( 'jetpack_shortcode_youtube_whitelist_user_agents', 'Bloglines|FeedFetcher-Google|feedburner' ) . '#i', $agent ) ) - return '<span style="text-align:center; display: block;"><a href="' . get_permalink() . '"><img src="http://img.youtube.com/vi/' . $id . '/2.jpg" alt="" /></a></span>'; - // calculate the width and height, taking content_width into consideration global $content_width; |