From a71baeac47f72245cf2d355e21cfab84a6915493 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Sun, 14 Mar 2010 09:35:26 +0000 Subject: [PATCH 01/12] make use of css reset for consistency --- public/css/reset.css | 53 ++++++++++++++++++++++++++++++++++++++++++ public/css/showoff.css | 18 ++++---------- views/index.erb | 1 + views/onepage.erb | 2 +- 4 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 public/css/reset.css diff --git a/public/css/reset.css b/public/css/reset.css new file mode 100644 index 000000000..1c85489d6 --- /dev/null +++ b/public/css/reset.css @@ -0,0 +1,53 @@ +/* http://meyerweb.com/eric/tools/css/reset/ */ +/* v1.0 | 20080212 */ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, font, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-size: 100%; + vertical-align: baseline; + background: transparent; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} + +/* remember to define focus styles! */ +:focus { + outline: 0; +} + +/* remember to highlight inserts somehow! */ +ins { + text-decoration: none; +} +del { + text-decoration: line-through; +} + +/* tables still need 'cellspacing="0"' in the markup */ +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/public/css/showoff.css b/public/css/showoff.css index 01026d35f..7902e258b 100644 --- a/public/css/showoff.css +++ b/public/css/showoff.css @@ -1,13 +1,8 @@ body { font-family: "Gill Sans", Helvetica, Arial, sans-serif; - padding: 0; - margin: 0; - border: 0; } #preso { - margin: 0; - padding: 0; width: 1020px; height: 740px; margin-left:auto; @@ -16,7 +11,6 @@ body { } #footer { background: #eee; - margin: 0; padding: 2px; width: 1010px; height: 20px; @@ -38,10 +32,6 @@ body { display: block; height: 600px; font-size: 3em; - list-style: none; - margin-left: 0; - padding-left: 1em; - text-indent: -1em; } .bullets ul li { text-align: center; @@ -52,10 +42,6 @@ body { display: block; height: 600px; font-size: 2em; - list-style: none; - margin-left: 0; - padding-left: 1em; - text-indent: -1em; } .smbullets ul li { text-align: center; @@ -102,6 +88,10 @@ h1 { font-size: 5em; font-weight: normal; text-align: center;} h2 { font-size: 3em; font-weight: normal; text-align: center; } h3 { font-size: 2em; font-weight: normal; text-align: center; } +h1, h2, h3 { + margin: 0.5em 0; +} + pre { margin-left: 40px; font-size: 2.8em; } .hidden { position:absolute; top:0; left:-9999px; width:1px; height:1px; overflow:hidden; } diff --git a/views/index.erb b/views/index.erb index 207ba843b..40c56409a 100644 --- a/views/index.erb +++ b/views/index.erb @@ -7,6 +7,7 @@ Presentation + diff --git a/views/onepage.erb b/views/onepage.erb index d76cbd60a..f8e9fce9f 100644 --- a/views/onepage.erb +++ b/views/onepage.erb @@ -12,7 +12,7 @@ <% else %> <%= inline_css(['onepage.css'], 'public/css') %> <% end %> - <%= inline_css(['showoff.css', 'theme/ui.all.css', 'sh_style.css'], 'public/css') %> + <%= inline_css(['reset.css', 'showoff.css', 'theme/ui.all.css', 'sh_style.css'], 'public/css') %> <% css_files.each do |css_file| %> <%= inline_css(css_file) %> <% end %> From d19d97c33062806b8f65bcd9fe68bcdb8312714e Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Sun, 14 Mar 2010 11:33:33 +0000 Subject: [PATCH 02/12] ignore dist directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c1e0dafa8..0a087e31f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ rdoc pkg ## PROJECT::SPECIFIC +dist From 082134e2adf19b7c914fd29eecb7e0eae41c1bc0 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Sun, 14 Mar 2010 20:45:27 +0000 Subject: [PATCH 03/12] Modification to div structure of slides to accomodate future changes - slide content is now always wrapped by two divs conforming to the css selector ".slide > .content" - in showoff.css, .slide is now the same as #preso to allow better stacking of the slides which will help with transitions - jquery selectors references updated to accomodate the changes to .style and .content divs - .content is now resized to centralize slide contents, and .slide is left alone --- lib/showoff.rb | 18 +++++++++--------- public/css/onepage.css | 2 +- public/css/pdf.css | 2 +- public/css/showoff.css | 7 ++----- public/js/onepage.js | 2 +- public/js/showoff.js | 16 ++++++++-------- 6 files changed, 22 insertions(+), 25 deletions(-) diff --git a/lib/showoff.rb b/lib/showoff.rb index f17a611b2..4ddb57d0c 100644 --- a/lib/showoff.rb +++ b/lib/showoff.rb @@ -46,7 +46,7 @@ def js_files Dir.glob("#{options.pres_dir}/*.js").map { |path| File.basename(path) } end - def process_markdown(name, content, wrap = false) + def process_markdown(name, content) slides = content.split(/^!SLIDE/) slides.delete('') final = '' @@ -58,18 +58,18 @@ def process_markdown(name, content, wrap = false) lines = slide.split("\n") classes = lines.shift slide = lines.join("\n") - md += '
' if wrap + md += '
' if seq - md += "
\n" + md += "
\n" seq += 1 else - md += "
\n" + md += "
\n" end sl = Markdown.new(slide).to_html sl = update_image_paths(name, sl) md += sl md += "
\n" - md += "
\n" if wrap + md += "
\n" final += update_commandline_code(md) end final @@ -118,7 +118,7 @@ def update_commandline_code(slide) html.root.to_s end - def get_slides_html(wrap = false) + def get_slides_html index = File.join(options.pres_dir, 'showoff.json') files = [] if File.exists?(index) @@ -132,7 +132,7 @@ def get_slides_html(wrap = false) data = '' files.each do |f| fname = f.gsub(options.pres_dir + '/', '').gsub('.md', '') - data += process_markdown(fname, File.read(f), wrap) + data += process_markdown(fname, File.read(f)) end end data @@ -183,12 +183,12 @@ def inline_js(jses, pre = nil) end get '/onepage' do - @slides = get_slides_html('preso') + @slides = get_slides_html erb :onepage end get '/pdf' do - @slides = get_slides_html('preso') + @slides = get_slides_html @no_js = true html = erb :onepage p = Princely.new diff --git a/public/css/onepage.css b/public/css/onepage.css index f708dcd2e..fda119662 100644 --- a/public/css/onepage.css +++ b/public/css/onepage.css @@ -1,4 +1,4 @@ -.preso { +.slide { margin: 10px; padding: 0; width: 1020px; diff --git a/public/css/pdf.css b/public/css/pdf.css index f79fc6705..ea1989b88 100644 --- a/public/css/pdf.css +++ b/public/css/pdf.css @@ -1,4 +1,4 @@ -.preso { +.slide { margin: 0; padding: 0; width: 100%; diff --git a/public/css/showoff.css b/public/css/showoff.css index 7902e258b..9485dc812 100644 --- a/public/css/showoff.css +++ b/public/css/showoff.css @@ -2,7 +2,8 @@ body { font-family: "Gill Sans", Helvetica, Arial, sans-serif; } -#preso { +#preso, .slide { + background: #fff; width: 1020px; height: 740px; margin-left:auto; @@ -18,10 +19,6 @@ body { margin-right:auto; } -.slide { - border: 1px solid #fff; -} - .center img { display:block; margin-left:auto; diff --git a/public/js/onepage.js b/public/js/onepage.js index 4382219ef..f4b4e1c08 100644 --- a/public/js/onepage.js +++ b/public/js/onepage.js @@ -1,7 +1,7 @@ function setupOnePage() { sh_highlightDocument('/js/sh_lang/', '.min.js') - $(".preso > .slide").each(function(s, elem) { + $(".preso > .slide > .content").each(function(s, elem) { var slide_height = $(elem).height() var mar_top = (0.5 * parseFloat($(elem).parent().height())) - (0.5 * parseFloat(slide_height)) $(elem).css('margin-top', mar_top) diff --git a/public/js/showoff.js b/public/js/showoff.js index 2660a8ccc..7394dd932 100644 --- a/public/js/showoff.js +++ b/public/js/showoff.js @@ -54,8 +54,9 @@ function setupMenu() { var menu = new ListMenu() slides.each(function(s, elem) { - shortTxt = $(elem).text().substr(0, 20) - path = $(elem).attr('ref').split('/') + content = $(elem).children(".content") + shortTxt = $(content).text().substr(0, 20) + path = $(content).attr('ref').split('/') currSlide += 1 menu.addItem(path, shortTxt, currSlide) }) @@ -94,10 +95,9 @@ function showSlide(back_step) { // TODO: calculate and set the height margins on slide load, not here $("#preso").html(slides.eq(slidenum).clone()) - curr_slide = $("#preso > .slide") - var slide_height = curr_slide.height() - var mar_top = (0.5 * parseFloat($("#preso").height())) - (0.5 * parseFloat(slide_height)) - $("#preso > .slide").css('margin-top', mar_top) + var slide_content = $("#preso > .slide > .content") + var mar_top = (0.5 * parseFloat($("#preso").height())) - (0.5 * parseFloat(slide_content.height())) + slide_content.css('margin-top', mar_top) percent = getSlidePercent() $("#slideInfo").text((slidenum + 1) + '/' + slideTotal + ' - ' + percent + '%') @@ -123,11 +123,11 @@ function determineIncremental() { incrCurr = 0 incrCode = false - incrElem = $("#preso > .incremental > ul > li") + incrElem = $("#preso > .slide > .incremental > ul > li") incrSteps = incrElem.size() if(incrSteps == 0) { // also look for commandline - incrElem = $("#preso > .incremental > pre > code > code") + incrElem = $("#preso > .slide > .incremental > pre > code > code") incrSteps = incrElem.size() incrCode = true } From f4eb63708ce5bbe8eb70581ce9347d9d0ee9a53a Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Sun, 14 Mar 2010 21:12:39 +0000 Subject: [PATCH 04/12] strip trailing whitespace and modified ul bullet styles so that block and explicit height no longer supplied --- public/css/showoff.css | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/public/css/showoff.css b/public/css/showoff.css index 9485dc812..594bfd3c3 100644 --- a/public/css/showoff.css +++ b/public/css/showoff.css @@ -6,16 +6,17 @@ body { background: #fff; width: 1020px; height: 740px; - margin-left:auto; + margin-left:auto; margin-right:auto; overflow:hidden; } -#footer { + +#footer { background: #eee; padding: 2px; width: 1010px; height: 20px; - margin-left:auto; + margin-left:auto; margin-right:auto; } @@ -26,8 +27,6 @@ body { } .bullets ul { - display: block; - height: 600px; font-size: 3em; } .bullets ul li { @@ -36,8 +35,6 @@ body { } .smbullets ul { - display: block; - height: 600px; font-size: 2em; } .smbullets ul li { @@ -177,7 +174,7 @@ a.fg-button { float:left; } .code .vi { color: #008080 } /* Name.Variable.Instance */ .code .il { color: #009999 } /* Literal.Number.Integer.Long */ -.results { +.results { background-color:#002200; color:#00AA00; font-size:2em; From 94551d873feccfdc9d62a669b3bd7d34b8841d80 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Sun, 14 Mar 2010 22:18:41 +0000 Subject: [PATCH 05/12] Introduced jQuery Cycle plugin to handle transitions - Introduced jQuery Cycle plugin http://malsup.com/jquery/cycle/ and utilise it for default manual transition - Slides prepared offscreen to allow resizing at load, although images cause a problem as they have not fully loaded - Popup help and menu render at highest z-index to ensure they are always on top --- public/css/showoff.css | 6 + public/js/jquery.cycle.all.js | 1280 +++++++++++++++++++++++++++++++++ public/js/onepage.js | 7 +- public/js/showoff.js | 59 +- views/index.erb | 7 +- views/onepage.erb | 2 +- 6 files changed, 1336 insertions(+), 25 deletions(-) create mode 100644 public/js/jquery.cycle.all.js diff --git a/public/css/showoff.css b/public/css/showoff.css index 594bfd3c3..52f1f4039 100644 --- a/public/css/showoff.css +++ b/public/css/showoff.css @@ -89,6 +89,7 @@ h1, h2, h3 { pre { margin-left: 40px; font-size: 2.8em; } .hidden { position:absolute; top:0; left:-9999px; width:1px; height:1px; overflow:hidden; } +.offscreen { position:absolute; top:0; left:-9999px; overflow:hidden; } #debugInfo { margin-left: 30px; } #help { @@ -96,6 +97,7 @@ pre { margin-left: 40px; font-size: 2.8em; } position: absolute; right: 80px; display: none; + z-index: 2147483647; //max, see http://www.puidokas.com/max-z-index/ } #help table tr td.key { text-align: right; @@ -104,6 +106,10 @@ pre { margin-left: 40px; font-size: 2.8em; } font-weight: bold; } +.fg-menu-container { + z-index: 2147483647; //max, see http://www.puidokas.com/max-z-index/ +} + .fg-button { clear:left; margin:0 4px 40px 20px; padding: .4em 1em; text-decoration:none !important; cursor:pointer; position: relative; text-align: center; zoom: 1; } .fg-button .ui-icon { position: absolute; top: 50%; margin-top: -8px; left: 50%; margin-left: -8px; } a.fg-button { float:left; } diff --git a/public/js/jquery.cycle.all.js b/public/js/jquery.cycle.all.js new file mode 100644 index 000000000..09ef3d9da --- /dev/null +++ b/public/js/jquery.cycle.all.js @@ -0,0 +1,1280 @@ +/*! + * jQuery Cycle Plugin (with Transition Definitions) + * Examples and documentation at: http://jquery.malsup.com/cycle/ + * Copyright (c) 2007-2010 M. Alsup + * Version: 2.80 (05-MAR-2010) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * Requires: jQuery v1.2.6 or later + */ +;(function($) { + +var ver = '2.80'; + +// 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 && window.console.log) + window.console.log('[cycle] ' + Array.prototype.join.call(arguments,' ')); +}; + +// 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; + + 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(opts2.currSlide, opts2.nextSlide, opts2, !opts2.rev); + + // 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,!opts2.rev)}, startTime); + } + }); +}; + +// 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; + $(cont).removeData('cycle.opts'); + if (options == 'destroy') + destroy(opts); + return false; + case 'toggle': + cont.cyclePause = (cont.cyclePause === 1) ? 0 : 1; + return false; + case 'pause': + cont.cyclePause = 1; + return false; + case 'resume': + cont.cyclePause = 0; + if (arg2 === true) { // resume now! + 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, 1); + } + return false; + case 'prev': + case 'next': + var 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 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(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; + if (opts.destroy) // callback + opts.destroy(opts); +}; + +// one-time initialization +function buildOptions($cont, $slides, els, options, o) { + // support metadata plugin (v1.0 and v2.0) + var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {}); + 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] : []; + opts.after.unshift(function(){ opts.busy=0; }); + + // 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.rev); }); + + 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) + opts.startingSlide = parseInt(opts.startingSlide); + + // 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;}); + 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 = 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 && opts.width) + $slides.width(opts.width); + if (opts.fit && opts.height && opts.height != 'auto') + $slides.height(opts.height); + + // stretch container + var reshape = opts.containerResize && !$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 (maxw > 0 && maxh > 0) + $cont.css({width:maxw+'px',height:maxh+'px'}); + } + + if (opts.pause) + $cont.hover(function(){this.cyclePause++;},function(){this.cyclePause--;}); + + 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.animIn = opts.animIn || {}; + opts.animOut = opts.animOut || {}; + + $slides.not(':eq('+first+')').css(opts.cssBefore); + if (opts.cssFirst) + $($slides[first]).css(opts.cssFirst); + + if (opts.timeout) { + opts.timeout = parseInt(opts.timeout); + // ensure that timeout and speed settings are sane + if (opts.speed.constructor == String) + opts.speed = $.fx.speeds[opts.speed] || parseInt(opts.speed); + if (!opts.sync) + opts.speed = opts.speed / 2; + while((opts.timeout - opts.speed) < 250) // 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 + 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.before.length) + opts.before[0].apply(e0, [e0, e0, opts, true]); + if (opts.after.length > 1) + opts.after[1].apply(e0, [e0, e0, opts, true]); + + if (opts.next) + $(opts.next).bind(opts.prevNextEvent,function(){return advance(opts,opts.rev?-1:1)}); + if (opts.prev) + $(opts.prev).bind(opts.prevNextEvent,function(){return advance(opts,opts.rev?1:-1)}); + 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 (p in txs) { + 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; + + $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') + $slides.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) { + // 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 + $(els).stop(true,true); + opts.busy = false; + } + // don't begin another timeout-based transition if there is one active + if (opts.busy) + return; + + var p = opts.$cont[0], curr = els[opts.currSlide], next = els[opts.nextSlide]; + + // 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.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 + if ((manual || !p.cyclePause) && (opts.nextSlide != opts.currSlide)) { + 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 (opts.lastFx == undefined || ++opts.lastFx >= opts.fxs.length) + opts.lastFx = 0; + fx = opts.fxs[opts.lastFx]; + opts.currFx = fx; + } + + // 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() { + $.each(opts.after, function(i,o) { + if (p.cycleStop != opts.stopCount) return; + o.apply(next, [curr, next, opts, fwd]); + }); + }; + + // get ready to perform the transition + opts.busy = 1; + if (opts.fxFn) // fx function provided? + opts.fxFn(curr, next, opts, after, fwd); + else if ($.isFunction($.fn.cycle[opts.fx])) // fx plugin ? + $.fn.cycle[opts.fx](curr, next, opts, after); + else + $.fn.cycle.custom(curr, next, opts, after, manual && opts.fastOnEvent); + + // calculate the next slide + opts.lastSlide = opts.currSlide; + if (opts.random) { + opts.currSlide = opts.nextSlide; + if (++opts.randomIndex == els.length) + opts.randomIndex = 0; + opts.nextSlide = opts.randomMap[opts.randomIndex]; + } + else { // sequence + var roll = (opts.nextSlide + 1) == els.length; + opts.nextSlide = roll ? 0 : opts.nextSlide+1; + opts.currSlide = roll ? els.length-1 : opts.nextSlide-1; + } + + if (opts.pager) + opts.updateActivePagerLink(opts.pager, opts.currSlide, opts.activePagerClass); + } + + // stage the next transition + var ms = 0; + if (opts.timeout && !opts.continuous) + ms = getTimeout(curr, next, opts, fwd); + 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.rev) }, ms); +}; + +// invoked after transition +$.fn.cycle.updateActivePagerLink = function(pager, currSlide, clsName) { + $(pager).each(function() { + $(this).find('a').removeClass(clsName).filter('a: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(curr,next,opts,fwd); + while ((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, opts.rev?-1:1); }; +$.fn.cycle.prev = function(opts) { advance(opts, opts.rev?1:-1);}; + +// advance slide forward or back +function advance(opts, val) { + 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; + } + } + + if ($.isFunction(opts.prevNextClick)) + opts.prevNextClick(val > 0, opts.nextSlide, els[opts.nextSlide]); + go(els, opts, 1, val>=0); + 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); + else + a = ''+(i+1)+''; + + 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); + $a.bind(opts.pagerEvent, function(e) { + e.preventDefault(); + opts.nextSlide = i; + var p = opts.$cont[0], timeout = p.cycleTimeout; + if (timeout) { + clearTimeout(timeout); + p.cycleTimeout = 0; + } + if ($.isFunction(opts.pagerClick)) + opts.pagerClick(opts.nextSlide, els[opts.nextSlide]); + go(els,opts,1,opts.currSlide < i); // trigger the trans +// return false; + }); + + if ( ! /^click/.test(opts.pagerEvent) && !opts.allowPagerClickBubble) + $a.bind('click.cycle', function(){return false;}); // supress click + + if (opts.pauseOnPagerHover) + $a.hover(function() { opts.$cont[0].cyclePause++; }, function() { opts.$cont[0].cyclePause--; } ); +}; + +// 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) { + function hex(s) { + s = parseInt(s).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.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(); + opts.cssBefore.opacity = 1; + opts.cssBefore.display = 'block'; + if (w !== false && next.cycleW > 0) + opts.cssBefore.width = next.cycleW; + if (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, 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, cb)}; + $l.animate(opts.animOut, speedOut, easeOut, function() { + if (opts.cssAfter) $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 = { + fx: 'fade', // name of transition effect (or comma separated names, ex: fade,scrollUp,shuffle) + 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) + continuous: 0, // true to start next transition immediately after current one completes + 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 + next: null, // selector for element to use as click trigger for next slide + prev: null, // selector for element to use as click trigger for previous slide + prevNextClick: null, // callback fn for prev/next clicks: function(isNext, zeroBasedSlideIndex, slideElement) + prevNextEvent:'click.cycle',// event which drives the manual transition to the previous or next slide + pager: null, // selector for element to use as pager container + pagerClick: null, // callback fn for pager clicks: function(zeroBasedSlideIndex, slideElement) + pagerEvent: 'click.cycle', // name of event which drives the pager navigation + allowPagerClickBubble: false, // allows or prevents click event on pager anchors from bubbling + pagerAnchorBuilder: null, // callback fn for building anchor links: function(index, DOMelement) + before: null, // transition callback (scope set to element to be shown): function(currSlideElement, nextSlideElement, options, forwardFlag) + after: null, // transition callback (scope set to element that was shown): function(currSlideElement, nextSlideElement, options, forwardFlag) + end: null, // callback invoked when the slideshow terminates (use with autostop or nowrap options): function(options) + easing: null, // easing method for both in and out transitions + easeIn: null, // easing for "in" transition + easeOut: null, // easing for "out" transition + shuffle: null, // coords for shuffle animation, ex: { top:15, left: 200 } + animIn: null, // properties that define how the slide animates in + animOut: null, // properties that define how the slide animates out + cssBefore: null, // properties that define the initial state of the slide before transitioning in + cssAfter: null, // properties that defined the state of the slide after transitioning out + fxFn: null, // function used to control the transition: function(currSlideElement, nextSlideElement, options, afterCalback, forwardFlag) + height: 'auto', // container height + startingSlide: 0, // zero-based index of the first slide to be displayed + sync: 1, // true if in/out transitions should occur simultaneously + random: 0, // true for random, false for sequence (not applicable to shuffle fx) + fit: 0, // force slides to fit container + containerResize: 1, // resize container to fit largest slide + pause: 0, // true to enable "pause on hover" + pauseOnPagerHover: 0, // true to pause when hovering over pager link + 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) + delay: 0, // additional delay (in ms) for first transition (hint: can be negative) + slideExpr: null, // expression for selecting slides (if something other than all children is required) + 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) + nowrap: 0, // true to prevent slideshow from wrapping + fastOnEvent: 0, // force fast transitions when triggered manually (via pager or prev/next); value == time in ms + randomizeEffects: 1, // valid when multiple effects are used; true to make the effect sequence random + rev: 0, // causes animations to transition in reverse + manualTrump: true, // causes manual transition to stop an active transition instead of being ignored + requeueOnImageNotLoaded: true, // requeue the slideshow if any image slides are not yet loaded + requeueTimeout: 250, // ms delay for requeue + activePagerClass: 'activeSlide', // class name used for the active pager link + updateActivePagerLink: null // callback fn invoked to update the active pager link (adds/removes activePagerClass style) +}; + +})(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-2008 M. Alsup + * Version: 2.72 + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ +(function($) { + +// +// These functions define one-time slide initialization 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(); + }; +} + +// 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, 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, 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, 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, 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) { + $.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) { + $.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, top: 0, 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, top: 0, 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) { + 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++) + fwd ? opts.els.push(opts.els.shift()) : 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)+1+count); + } + $el.animate({left:0, top:0}, opts.speedOut, opts.easeOut, function() { + $(fwd ? this : curr).hide(); + if (cb) cb(); + }); + }); + }; + 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.cssFirst = { top: 0 }; + opts.cssBefore = { left: 0, 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, top: 0, 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, 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; + }); + 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; + opts.animIn = { top: 0, left: 0, width: next.cycleW, height: next.cycleH }; + opts.animOut = { width: 0, height: 0, top: curr.cycleH/2, left: curr.cycleW/2 }; + }); + opts.cssFirst = { top:0, left: 0 }; + opts.cssBefore = { width: 0, 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; + opts.animIn = { top: 0, left: 0, width: next.cycleW, height: next.cycleH }; + }); + opts.cssBefore = { width: 0, 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, 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, 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, left: w }; + opts.animIn = { top: 0, left: 0 }; + opts.animOut = { top: h, 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, width: this.cycleW }; + opts.animOut = { left: 0 }; + }); + opts.cssBefore = { width: 0, top: 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, height: this.cycleH }; + opts.animOut = { top: 0 }; + }); + opts.cssBefore = { height: 0, 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, width: this.cycleW }; + opts.animOut = { left: curr.cycleW/2, width: 0 }; + }); + opts.cssBefore = { top: 0, 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, height: next.cycleH }; + opts.animOut = { top: curr.cycleH/2, height: 0 }; + }); + opts.cssBefore = { left: 0, height: 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); + 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, top: 0}; + opts.animOut = { opacity: 1 }; + opts.cssBefore = { top: 0, 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, top: 0 }; + opts.animOut = { opacity: 1 }; + opts.cssBefore = { top: 0, 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) + opts.animOut = { left: w*2, top: -h/2, opacity: 0 }; + else + opts.animOut.opacity = 0; + }); + opts.cssBefore = { left: 0, 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); + var left = parseInt(w/2); + 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]), r = parseInt(d[1]), b = parseInt(d[2]), l = parseInt(d[3]); + + 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)) - 1; + (function f() { + var tt = t ? t - parseInt(step * (t/count)) : 0; + var ll = l ? l - parseInt(step * (l/count)) : 0; + var bb = b < h ? b + parseInt(step * ((h-b)/count || 1)) : h; + var rr = r < w ? r + parseInt(step * ((w-r)/count || 1)) : w; + $next.css({ clip: 'rect('+tt+'px '+rr+'px '+bb+'px '+ll+'px)' }); + (step++ <= count) ? setTimeout(f, 13) : $curr.css('display', 'none'); + })(); + }); + opts.cssBefore = { display: 'block', opacity: 1, top: 0, left: 0 }; + opts.animIn = { left: 0 }; + opts.animOut = { left: 0 }; +}; + +})(jQuery); diff --git a/public/js/onepage.js b/public/js/onepage.js index f4b4e1c08..c1f3ad606 100644 --- a/public/js/onepage.js +++ b/public/js/onepage.js @@ -1,10 +1,5 @@ function setupOnePage() { sh_highlightDocument('/js/sh_lang/', '.min.js') - $(".preso > .slide > .content").each(function(s, elem) { - var slide_height = $(elem).height() - var mar_top = (0.5 * parseFloat($(elem).parent().height())) - (0.5 * parseFloat(slide_height)) - $(elem).css('margin-top', mar_top) - }) - + centerSlides($("#slides > .slide")) } \ No newline at end of file diff --git a/public/js/showoff.js b/public/js/showoff.js index 7394dd932..b20e6b7a8 100644 --- a/public/js/showoff.js +++ b/public/js/showoff.js @@ -4,6 +4,7 @@ var preso_started = false var slidenum = 0 var slideTotal = 0 var slides +var currentSlide var totalslides = 0 var slidesLoaded = false var incrSteps = 0 @@ -31,10 +32,25 @@ function setupPreso() { } function loadSlides() { - $('#slides').hide(); + //load through #slides offscreen and copy back into #preso when prepared $("#slides").load("/slides", false, function(){ - slides = $('#slides > .slide') + //center + centerSlides($('#slides > .slide')) + + //copy into presentation area + $("#preso").empty() + $('#slides > .slide').appendTo($("#preso")) + + //populate vars + slides = $('#preso > .slide') slideTotal = slides.size() + + //setup jquery cycle with default show/hide transition + $('#preso').cycle({ + fx: 'none', + timeout: 0 + }); + setupMenu() if (slidesLoaded) { showSlide() @@ -44,7 +60,23 @@ function loadSlides() { slidesLoaded = true } sh_highlightDocument('/js/sh_lang/', '.min.js') - }) + }) +} + +function centerSlides(slides) { + slides.each(function(s, slide) { + centerSlide(slide) + }) +} + +function centerSlide(slide) { + var slide_content = $(slide).children(".content").first() + var height = slide_content.height() + var mar_top = (0.5 * parseFloat($(slide).height())) - (0.5 * parseFloat(height)) + if (mar_top < 0) { + mar_top = 0 + } + slide_content.css('margin-top', mar_top) } function setupMenu() { @@ -52,7 +84,7 @@ function setupMenu() { var currSlide = 0 var menu = new ListMenu() - + slides.each(function(s, elem) { content = $(elem).children(".content") shortTxt = $(content).text().substr(0, 20) @@ -62,7 +94,7 @@ function setupMenu() { }) $('#navigation').html(menu.getList()) - $('#navmenu').menu({ + $('#navmenu').menu({ content: $('#navigation').html(), flyOut: true }); @@ -92,12 +124,9 @@ function showSlide(back_step) { return } - // TODO: calculate and set the height margins on slide load, not here + currentSlide = slides.eq(slidenum) - $("#preso").html(slides.eq(slidenum).clone()) - var slide_content = $("#preso > .slide > .content") - var mar_top = (0.5 * parseFloat($("#preso").height())) - (0.5 * parseFloat(slide_content.height())) - slide_content.css('margin-top', mar_top) + $('#preso').cycle(slidenum) percent = getSlidePercent() $("#slideInfo").text((slidenum + 1) + '/' + slideTotal + ' - ' + percent + '%') @@ -123,11 +152,11 @@ function determineIncremental() { incrCurr = 0 incrCode = false - incrElem = $("#preso > .slide > .incremental > ul > li") + incrElem = currentSlide.find(".incremental > ul > li") incrSteps = incrElem.size() if(incrSteps == 0) { // also look for commandline - incrElem = $("#preso > .slide > .incremental > pre > code > code") + incrElem = currentSlide.find(".incremental > pre > code > code") incrSteps = incrElem.size() incrCode = true } @@ -158,7 +187,7 @@ function doDebugStuff() $('#debugInfo').show() debug('debug mode on') } else { - $('#debugInfo').hide() + $('#debugInfo').hide() } } @@ -255,7 +284,7 @@ function ListMenu(s) } newMenu.append(domItem) } - return newMenu + return newMenu } } @@ -267,7 +296,7 @@ function ListMenuItem(t, s) } var removeResults = function() { - $('.results').remove(); + $('.results').remove(); }; var print = function(text) { diff --git a/views/index.erb b/views/index.erb index 40c56409a..9b480bc17 100644 --- a/views/index.erb +++ b/views/index.erb @@ -11,6 +11,7 @@ + @@ -31,8 +32,8 @@ <% end %> @@ -60,7 +61,7 @@
-
+
diff --git a/views/onepage.erb b/views/onepage.erb index f8e9fce9f..28430cbc8 100644 --- a/views/onepage.erb +++ b/views/onepage.erb @@ -20,7 +20,7 @@ <% if !@no_js %> <%= inline_js(['jquery-1.4.min.js', 'jquery-print.js', 'showoff.js', 'onepage.js', 'sh_main.min.js'], 'public/js') %> From a92cf9226335995a1103fa06bce5eaf4ab057921 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Mon, 15 Mar 2010 14:28:53 +0000 Subject: [PATCH 06/12] when loading slides wait for any images to be obtained before initializing presentation this fixes the occasional issue where an image is not centered correctly as it has not loaded before the height of the slide is calculated --- example/one/octocat.png | Bin 0 -> 16539 bytes example/one/slidesA.md | 4 ++ public/js/jquery.batchImageLoad.js | 56 +++++++++++++++++++++++++++ public/js/showoff.js | 60 ++++++++++++++++------------- views/index.erb | 1 + 5 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 example/one/octocat.png create mode 100644 public/js/jquery.batchImageLoad.js diff --git a/example/one/octocat.png b/example/one/octocat.png new file mode 100644 index 0000000000000000000000000000000000000000..b321b3dc6212e475dcd74e00db2c925e064ebe04 GIT binary patch literal 16539 zcma)kV{j&4u=f*dW82tlY;$AVwr$(q*v7`T{lvCyXXBgy`{Av+-)`0P>FJrSnyzzB z_57wW5%RKP@US?r00019Lj1SlHy{0vpdr7)Gkk<1|UiR?2w=w!-2#r0!HbSN6`SISb$ok z24h&j9{|AG!&`_1Pyr9Pc#zII0WlzebSg12P=OABzDj^14QOva zAg@w@gbuv78pL0tnMn-PzY7B38mk_UD4-AUPZy$@01$D20)z=rC&7rM!SWd9dUne7 z>_b|`K>)qL)AI0~@ylb};<@@w~ z_jBFz2H=n(kY3eW81&&_VC!0~7<&u^7h<%1J|_Jf3Gw@g{W-hGQm0LW9(k)C(JD_O zGvd*vnDCo;EO`&*)Q{9O9M&rOG z0FcaBm^_{VfTW(6IDuavfXURNeE^{I1WUW@52o}mGyw2BFMzsM5b8%CT4gUnRv&(6 zFD9q~NNR54r9Pr0GDB1z%_Lz|R zSULSzouM$`f}_x=2E<(9$cC{iBva6s>9OD>2I4G<{zXKm;b;mZL!*vGpyfiA2|D7W zceIXZoH5!0ukq`nL`;$Ik)2|Ue*)?iz!pGV1lr07aUzHFoMxR_5Ow@h3an;v8VPv) zn+r;3rA}O&0X~tjM*g#m2&U1i2HMeKBKi^PI20ooMu+OGs&TAF`0DJg=(xQ(2G`JJ zpi%y)7tp%FNd4A<@$q8n((1xxy2hjEY zl|-otE%Au)a*1za0|zZ=Ttne|(l7;Niba1=Bw0=P55bFbnS|2wDikKma~7a0!ntxa zC2aCs<>{5e%28QdGRP-0F@%9dw1tZ^85U+1&*t=}&h0RpK?EYHGpTb{Cs3!yr$G;H zKj1^*gGR&+sj#iEy|7EMTCnNUrAr{@Q`1M48J3xF)6LQl)9h5#sh_C5(G$i|lDU#q zlYNtqE0k57RQMM?D&Um=sv!Q=RrM(mRcVmlFNayc_`6t+uhLP@Rz0QYrWhwbt)N%f zt@jc5Y6M>&8X}q(Dqg5;)G~}6LyR%ZWOA!6wB)D?c1~lJCS#~o|8gPi3h{>PO7A7D zB;luy)~?VV(!TC8ea1I$bnbBq^Em#9aJo4w_Gt4^_=tIS zy>vZG$j-n5%@&Vs&B$SNGZAleVwGmmI(rkmTZRlYZ%-IBFPxPqq->?Q3Nzbhb;sm0 zt+c~4tYq0T*|6djkbpt_jB&&qmu0!_x@}H`M{}~8LnBrQ}#V8W{Ffh5GB<$6;sKkG_uq-*Atk0h;!9G z*EIiFnAwrJQMGEbusOjyzNzYUD8dm&D%}tyX2eh3-zA! z#{CNXi2K*G>v4y1D+{3y(g$(~(iMOc&;VuyMhKn`UJS(w5d+ZyN&kZnUFZi4yau6T zl3g$69qx+}^M)Bs#w_|cbT+ys?kmFtg*3qua%|`{^fr>OUCE2|=|nSh_>P!$cq^d= zb~@&Z586*^rV6?BkW*9leUmgkAiEX6!GOE9qwkoGr9ad>M|788iDpZ8GNNN1F%+NyBB4_&RR}%bz z$C1rAZc^Cz^8x9L)BQTSb%^wAVWVQTJOYL^ec3N}Ei5hfR`D)z%?0Ld)6cUPQn)}2 z@2>b-`PSNol~#9++Z~b~kq!*fC?!lcIz}DEc4K#on>in#Ij}zELw-+PQRU9kW8*GX zF=(#1Sol|<8cTBdpE00q^@C=c5xPOLvC6e&>Y|paA2nvOUZs6yS@pkK(bl6qHCeqy z??(@twY4qDmhsDT@$;f{+sbE+o*Kz6OTopN&>Q$F+}oH#Ts<4fE$4hs%g5Ns#>w$X zFjfQBORb6K%JsW^w!$aRY(E{K>POYzmhM%GwWXd-H?MnyAbfQ0t?NG*olU>o)vUTi zd>(D*t^zmXa13$VdyafJTgBYuhH~P(ioKwoM6S;*o$ahQYI=I=VQduHVhF^!><=^j z?bb3cGu)c&HK`H$1rPfuw@bXe_T^9Vrv^3#Cb!f5S{|X##XWw_arL-V(iYm}@#c43 zpF|gC%^UNi0+xs0&JspaHlQ}N!u90Vrqml~JmWXtmNE~IaGJWIc)Tj?n1 zbeRcH=kQ}XUrD#+(A)p)9% zA7swCXRqh|UM+hUotFPC)9K`TbX^Z$;I`OOY~r<&w?F=KeY(VSgT0d8(D96OuX*oY z`#6JoMLhFs{H!zSwb}Wn->W}8pn-Ue027w;`R8jsY-ka34`uoZa+)LDSPqjz+z2o)Y@*1uY(h-O!DF2Z!GcY#m&``K5ckJ` zptAegMYdZS`r^w7znQ7+c1N~}1)S8iiUK%tprJ5ohl0_CsEi>^1Z^`J1&$wM1T9Vs z#cWy`qbQ@Qz)!Z{0s`QtT^IE}cG-7t`xA63jEGmi&r0Y$Ox{=kllcLgo240vuUyi=RkXkPd|0D8IT!(-^-TA zB-j%RN&p&bQEJwNjRmjFjYH-#1H{1ji=S!0efJWh%}~I(4N~y*Wa3Zf_?*18{WLCsLteF3i_v=>p9Q0X!rEgiueg@CewK($>mY#b(VeF4k%J;Mc zZvS`I`#pDpF2-{ngb0Eeq8kYk$37h37C2KvWeY+v-&*~AViZcSCJ2IxaNKz5(m$=8 zpc6G$0<~#Rh*)b^zgNrxNi3=ek~#qXKNa*|95FT}P^*CKZwV0&e^nZ0LhPvg+cL(9 zQ%iaZnb|7frUIshLK*S79_MOf_O|aa64~PoKG6lV*?6NCUSJVIY-1s1tbU0sa{%+V z7&`fuOd9`l)fG$_FVLCp^AOrlvc*l}S;WIaIv$7*A|2&gC>$RvMtBhXht$7(`-#}f zmlOO{;C&Ujv(eJe33|?fBSW}m;Jh)`#=&@&D~t%=KNUYf3iu=!Msyhm6Z<5-j#2V4 zKG2LiM~ivRWQ?x`bqYm))8%~b%!OV2JqxP2DEE z5U=fwX~tS?lUN+rFpE@82i6ELu<d4&G{~6f-f$rG8%xbi%5_f zS^$kEqMw1$Zh^e)QoxukP9w^JLy8w;l!mV*+`sR*``mu(vEj~3$3urnry`<+9t@ao zWROl0r;&Bx5E5|-w`W<>h-;*;hwa=&I+#)L-w3WZQm#Pyak`u|MhfL{Q2Y7gR7w2$ z-I^%~#G8QKRz?IFR0LXD3O3s|Z*_42 zo3sswqzswlw?!yXs8Q!wp#c_}L;@;kEGk3$OE;by|9EXdbrA(~!?N;nHzt03Kf*Bx zq#l&d5tNVVgU_1}Q8x}ZPHLb^!m%up1%(Dq8c0@=8BC%;{nv6;Q*roglKbTV_~_kw zXT^3&b6Pf%Wz;gKjM?oBeJ?Arq-CjQZ1S&dCs@M!dT>k{YYx#ZlrR`D0N5-`Vt8AI zzhAyEqYQpmf|dt|9{Oz5!lwc9rT&~Y^V3XG$;G4$j=%nmoL2#rQ@YzGJwN4KKdrJY z2D~a*6j#H2kW)H%p^cIkVTDtzJUm^!Pwz6vX6(}W+orl2`$`c;6c(!#z`k}5nmUy+ zzL}aOxV@*Fca9XpN+j&X`vQ5ubuw*df1@vGhgb&dzCi?@>r6xg%*?FgLKn%;`4iZS#;O7xvGeK@~jCfOxijc zQ0wXU-g^I-#$qd@SLVc3X8l}{DXZA+zm^`kTxvbZ;csfvOT>Unm=g?YJk=VT9^WZ` z^CKBk$R^{Yf%}2~kY*i9*CWN9zuZ^W5!UK_h1x#fl;t$8OwjX^_=oTxf*SmsDYyc9 zNU2>y?3z=}FsPm%B(sF*Bwbxh*>0INN*%D9Yq@(?uqd%!S8D zR5Rep)ZSw zQ-}AgneNvODq+$Z2Xm)?Mhut{9S>#A|;4 zMH-6kG~g!3x3D!dFA`J)CPyyg18~)tCa3_z2A3Yt+Obv(ky?wX4E?#T< zKJ#CE`f}$x@wc~P+Y0b^xHU?~67@ERrXa5OrzV8%q2#-CwXp@2M2f+*%rJ^EN2z8(3>Kzp1~-L*<8>qowm`C)|Q)mE5GSA0jWz;(5+#k11S z--{*it)ST3-u85u`gLasVd2Yb21Y7Dom<&rNb|wbc%#&1UzYb)Uk1leP7Y=!e)Hb) zXxe>0mOd}(l`FN@iEd_EUOa4ppmCYy`=L$ErNtH`ZWhAvO;wy!lqY8P3W(|XnJa6- z7at}q6)o1LZyRpbjx2Pv70XhG!;jW}&zF#xm$M#DBqbmko98ul!-m%0hvdp}rKcUL ztb44i*6+_zZ#@$i2)1_jQ|$&!2KL)aPtK{r@n}TizN+zol|L9zWY#nt9}th0{TjSx zz4ug-p_^XX;6)Z!IQ?{k%;lS%?YVy)WVZQH9?hWx%hx)Q7cVWIkQR?kuJ`1^Ra95_ zL^Y7AdKzjXE06v-Md@W`a`JV}#%o4((sc$?7hw`J2s)dF{qms$!)$ z8qFBa9_Kw3tM%9k6CZE^*?Ztfq_vB=4Qc4Posu44yVMI1jmU%-k0*?7|iKJ}> z;|Zt?1q#vfR6lo7*z)%l7vZOhU1XVBkf4e>1}pv^+^vzpVEnD*xgkIyFf?d-7Zr|$ zv>>FhJ_SiI=W%dWXJ=5Z1CBxxXfEw8ARrr#>B8EX_#8{qv#IPEd8T}x~4{T(_ zXi~nb5HcWf;Eiy0CZ1=$Sm`-?%6s`xmxu@U3pupeLoi>`OLKR1qEhIcSL>LOLo_7n zY0(b`fv!rP^UrTusothq#8T#|iSx-GU@)+ORCV^HRYs zvJ&sn>Y4nLz!}pHJ2EUEbs4pNYlqKtj5knf$r~0Bt#Qu7OMl|yS%phcTdr@Zj11hM z$&i7@5Q23rD&d3u!)-~ke%zUKgJVh~dgLGAUVr&WGP^cK9FDI+qWlvTJzxX5P(j;u zv@QKJtv$9z%Pnx|X`(e>xQL5b&^1-9sU%g(T4U7mH{>4*z5o*BjYOL+Qb?Z7YphhBzS3<(kT7TPHJ%zqKQ96*olh+F3l`V#sav>fvC|85 zAr@9>4f(UeeUwat!VC!>^l{pwp-=}QCLky%yn>|It@r<6OQ3~e!v498{|glm%_s7Z z?!k1f=LzCws)`zjPGL2J2eJ7D*O)a@E2-K?YN2tE%IWZ`%<22x#1!6(Z;;&~@i4?QL`)Bslx1aca`S4z(J=0N9 z3#ruZaYe3A&Pdf5uNXJE(_H+E(qV{Q*`9el($jb;}s)=eb>*|y(6 zf~?7Rp|)g_ABi$9TflL>O;`Pvn*eW^GT9K(vYIttubxvp28w&=At~gfy8EX1@u}!F z<)*+dU9;=Np|m=z)gZ|E>j&mBbF4=gwf@9aCZ4qnW0BNm{xwrgB>rGSI#Ik(xumGv zGh3PE)!R=zS8s+mbro`KUM~gbaf^c(Y_~kZ<_GvwF;+38o>VtJ%_#|fk38}&O}O{< zPwv1hhRQk^C8NyaWcZ0Y>bEa07ym2hz*Za9rA<={IjzaX@@ASh_FG6ANt$uH=h!E1T`Y@h5a1|7lz7CpQ+XN@MRc*ADlmdcJ+5AU?(hXTN8R>Nlom%Evf2^!$FTt2R$HDx#C9GH* z9eKjDcYu>2=-G6%S*5OpTD5)J$*|+zc0sO0S*KmGZoy~s;NqD$uZv(9Y+j7S3Dy&K z6=Mgxzc}e7$i%YIncbo9UG0sC@WqN8c0V|D^SGP(n?xFZ6q;>COc0cx)VDe4_|F}D z$%n*Bs%hzZMw!|*1&O+*|1ve9MBW1(om-M>V$zydP&xI-3!NWaC_YqQCq-inj8;#4 zhOhz(A~YYO9lhonisJ%kkCnmoesi0O#J!bRC!2yNQP8?buLN7bJDY>+>Rl_&zqKVE zQ7x1rBrJpV_W^5{aD0OG;EfFZY@glON@W8Ob`qyXl#~_sr!lW5bc*imH#bzfF>>$O8U_I_iAnKKT??yG0(F;gHSv-G(gwN&&* zfjngC{^{=ZFB|>}WVRkgMy8kz!|YDw`EKa7DCG!ibTV#B!eRAx9b*pMxHuVfUC$Th zUs)^>XD?%OdSfC>xu@IA=#AVur9?RY*9BAc`_)*zsGZrVph`kf_%JR~VZg1r7+M^h zp(k+eX`SZ}Dbdb8WsgrNfA^op&TW|Y$OmCa`y!c}rUYmdY z`%E7Zma%!WYgrmK*KTVFw)wThXg&P9t@=&hrUW{=wNK3nbKdP;K5+9sksWRwM+2MZ zV~<@AeB3CW;0Kbw~2z{~A-3Me{ ztujb})I-siUMr=_R`0C(wFa|Ji#;tj=6VlkkS`r=JZq-U2b@Z{Zb3Ys3+LO<8|JbQb{ zNJUi+-iQ(U~(BRPJXifJ;}0+Be9$ajxpvhF(X*3Zxme*uqiq0^FFCAA#C-Ge!z?a7tn zPv5rZW>d`it}Db!Z2L7IMSIJc1E`i0{(7t>haT+`$srqS@214(4dtfei}|@9CY3~i z!u!w`ezY?eE>=+K_2tw|qa!@HwK9^5UUZE-faSd5&eFm?*6(H`@S|n}(sL>d*mgUM zsorLwRbO%`7ckOM0B~^$^v_c1!flQHI9JbT=0xv{CKYvjY$Ky-N^-ACMgB8hfdr| zgMPlopZY0^fDjq5 z?R`@^L zCh@hkd76|f^PEK!D9A5ZgS&W`*uSccqCbZt&cf@VCnh=ozDa}@qks?FP*ad``9{6c z>O}t?;5q=(a%(hLKyd@98MI3BT}hAG2*i%I@!7;p0uM+~$!Xspl3V6oLcuUel2$|U z<_6FL^R}gA83a^&#biTsJ1dDa`T*(Je1Uw3AT>}mz>xLgT^9@UjKGpIsz?Eg8v+_& zeVy4LbtDO`T1j7LxRzmGX8mLLBjpw4yolmr~OpZa2?bvuwb zUz$QbOd{JA;fR%Hb3y6qp(uB2Ngi28o7+>>S*&Xxdpp%CDb;9eWxMYRLg`!ZTI+*e z(SDbF=|S?qdi!e!qe`HXq%}u0g0|7U+wM4P;aVZU%}qmb_WLIIfUu;(smzCm9%kIl z`?_N*O=S$Vlk45Q^CI%$m&5BU!|V=AA4oPEcA&5N&W|mm+Mc6T3Vx@y>m)iCT`S#) ztoVoU>#o5ATR{aOeV@Y)Vl#rV`5Tq-b|33LlPO;>e7<5v0yLnsNA`~pb32Dd>%^2) zyTS=tF4Bt=P5KbZ?6#Ru~#&iw}Qr>YScss z+7R!H$hWc-;p~)Q3W%MuN61Pue-XQcOJF=WdE{r}SaD5z-Yzz-v!NN5*xC@n^~*Dc zVN$c?Zqs&YyiZ+JY2OcYcXDLiV|yTNrRvhbL=d8^O2#O^VzY4#_dyE>P;y5yYXr`smxOl3CjFKsf9%3Q+;`V{{O7#JC z%>U>ZRirnk!(^u83+pBgyW9O`cXL=UM1*=wG0%vu3Q0sc-(Gyf{fWjAOV=n$dI&RT zbT%gK_k^wuLg)!^gTtwYPPf34)3TXR*a*l?rqLRn_$*elKYnGPm1h!wX*6(RR#LZL-Vagp3CV<#C zdd^{R^TJcJEZTpW<$>R}uFOmQoN_n)MqoJQ zr?;2e;~PFc=R*{QHQg*zzf|Jzmhcx@Ph?851xhlWQwjY$qX!c^TG|HrQX&b$i&tu> zQyAoj*Jft$5ydW(v`pZUu}qLqT&GQds5H%+oz)L&GW)B6exu9bTw@ewBsD?8hufTI zcGe8lD*Ezb`nM@g3mW6Pk(4q+KVS-Q*0_m!dBYOMMY25vU0^QX^@2)LtjGG8^hGi+ zg|i82uvb3fw7i`wGB6oWI_$LVk?Lh5$OG2qHiTj9>BH%m@Mqbz-wUMc&g=0eCf$L? zi_OMlv0qMe%?GuuWh5;$vW@bycoTZ=5(^fojXO zQ4{H_&d^|eZ#cz<#5wW76a2RLOBpro{_6S__fE&2!a(ajpg^zMWOqgci9bwRI)Zn@CV%^(ca=7}g$ z(v?kO#S)0OgHH)>)uWdQK94?gopQa>+oroVRC)DU`6p%!0~;5_Rstthc=;Sg2Lz+M zcj#RCmset~sP#>NF=MKz;QHyLQwV}6`Jm}e3#(*|2~C}vl1L576c~7>5S!oWK7!)W z_rJ$nb%+Xyh>Ok1kUw1pU+fzcs|wEJ@DR2!w%KL zCtbIqAD!oCsApT!{UxB^9F{d6g-}y+eqA-^W3N-RKNRkSlrDsDX@|c-f6~A6p|5|N zw^ILjr~j$()cv1Xy2ifqr~-1v#eZf;4Ut0F40xLDM-nWk-r^e;GyQ845(;LURV}UX zDw4J=PT0@Ahjsm+Hiu(>mm!shnvoL{4*J)~F%XBqVjD%!7{EUxx~_7~Qai z={OKcNf?AK-36sGEQB7J@9J?m4?}9Oy_evjRh*z5v3BLN9}oneNzLrn)`8gfh3B=> z$?D147HhdRO;-Lu`d#L6`t83`V??}jq`_ID?4TT_o}mbO8iNxN{{97(2XV^>V7U1F zFTVp0Q@#(*q$|&e%Dn^xK?JbCqF}^51XG6vUPPyHzoSH6W29Nh%=VutcV%L|Lit}7 z#|-L^+0Xb71PI?I9dF_e!7dtHdy7 zeEMOaMNTuo>*7h1<-fDPb~a(RSY14yHjwXPB!bU9~ zOM$^~=DLXal+l6$_v_hB_3J~o0Nranou~kxFeBcBqXLr#;)yP#o*rGhyKlR-#Kiw7 zs1gJzjmN*cG&i;+K*0*7x}Hj_0WX=Vsl&~nU~i5{k-`ebDD9tP!{`}5)?!jXVtN3# zum~L0!|Rj^O~<9AE8Xk0!C}xr9A~1D@0%GcWvoa|f(5aK-ezB*JG8PKBx$!FEpKeb z*jdk42CY-h0MkP=WjKYfSS*L|RDX8%+;TtfWEDBy-m{*qAnXWd zGC`bBkE&Rl9=N#lzG(h0IKLWiLlqkqxEx6yMq*8nbRQ_Dmu|C@`zj~(&l7lMJFRtB z@Y|!!=$3VzVBor&y2cw`~eLj}s2(>VjVcv4!VG20oX5NYga!R`% z3OxRVB$n4a?E}|~F@`Qot0rs*DfE$h9h?harOpX2Zh>b-$J_gHR?zhXM z=bL!_dQWh-F*(n6RvZ5IU-U!U`+~tZ)_&PmahVx4%wc#xX*MZikBZdz@|GWzG(Y*! zLZS;kX(I}-J_&rHk@;I87WX44B~YXuU!fmP*7rVNI-d2Sc@wwGTTGM`%VjQmJ+)v}Q zbP?i=%O5)09sA&{`0ycmX#L)6=a-5d=O_N9p;qYW9rH$%VTZD1+tZuv(a91HkGE17 zgWkux7YTQ#ja`h&_rCfV(HKx-iG8fabz*>;PnIG8tYk*O^-)#85qfyvAdNDqJA?99J{hbCh{)!(D<$bge>3g5 znYcux@=B>3#p8N-XxA>UN(+=%PziDijq6X_r3?%`=svSv%+Vo(x&cR`Xh9a(5Y*B+ zn+ec|S~?gM8sC~vLBeLufr3nuw3BNano8A^ zTXaK4!D5I8x>27=T#ijiMapyYXGz6Lpw0}m2IoP?kf6)fHi@J4K?3)b z^aIHM3fqED42S}uX9kGS*fX|iVH{UpuvEJ)dDWq1<q2)U^h}LWisVL8_5e z_s-PMC1I&~aO2_R{MSxit&H|_J&GV!9|!4TKCBbj2!%kYeb0%l`w8?)Ix#}>HCUg7 z!tLLkdKzzdagMcb(Ad8L5m$t$%tnDGX;b%m_r86Dc?I4Lhj{d=wJ+OzTz z6n=RbqaEyHqv69X3Kgy9JTa6Su}N$$*xf{mYHpyM>1}WD$il^jY-!5Ng?%5ExF$W4g17Ir~u-abh45U#}vS*si)et5o~ImH3S>M#y<6 zbah0AUX#mg)16pODx*dToqqT4Te{hpO_3ifH284mWE~u59g3n|Qla7hQK0cd^=--QwGU*5}7Wc_ZJn3_qzbD0K9bNw+I z-Zv#eNXA2F)r$l>OsLeOI2|r{eOj8=j=CJU{pjjbE&bHlii9s%{3NS|`^ zTDiY+v&}Bw#U$9s8rxbhBQ@WuMOBFu=;ey6VOmpj~@44iondpNic>EHa` zVbFAgLh9e8eiypnE!1>;7=hSTyb(u1_;46Z*A@3=|6czNV!E_p`<^ysJ-vE=W7yv{ z$<)&K1EHz8Vl_71p)R7=B%wOq$(3IV4C9c|pSzPVzg++LG$mdVcE6;vY;k8O;)duuRt`u*qbV{GRKACsrs z2+wHOtnkeF%FpP|yAhb_x_89q!Z5?fe*Bui%1N3`UJe5d^${|WNNke^I;gw36RG6PAI_baet zj#VA%QA)v&^K9AjF;`ns0M zakTs;R{8xYt2f)r)ZcmE#k~6Id%q|<@_vFr@p0z6w+Qb|3v%@%eMzs)gS~@KYoanXnTR`)^ch_=_C6liTn;1`eg{Rbab zbo%>N^lV<)32M62j6J^4q}43hUHTHooT@rg8^5}NPtV&HPg!CcuTsNb5636@A5tks z#L&sYMXDI_Y_!}hGzcZO2I*YT$(38MZCz^?b1Ma0x&xK=;SeS1q2QdZ2CvA240(Et za%S$W8#C)S0aUd{5WlSisxnnt%(l+?Wy&phu;W#r19-I3d}@8Rw6}OlPpd#T(>0_! z?^~i<_oyH2QObGQBqrSdOkcfm{>pvlO_}{CxRu2-mG%bFSD-s+nP&*K@Mpz}7Y#vM za%RVl6k$vHgtOBmp&O$dMP08e?kC2D1SRJ@01~sb*n!idV<7gAe^W2t+uG*f$E9E1&p!gK(Nt6!VMf09L?5!e zQHOr-=8&52Hx*(o^ppFU)-Ax_eg%Fv?!Rtj@xeaLcTfe`ELJ8ILbJ&jqW`f?=B*EyfH z`g`gy;n3OkkvxiLxhF9XutcJvAkd-LL8-<8deg&tEy^rfeDtl8N?ivVd*}FP2DRfhpl1+drUd+A(zV0KJr~uQJ*QgWzBCU4o7Ni238JcUW^|z$+U& z)EUqKW#yj_$sI+0!GIxJp9psuR#6(sJO(HwwTNX&)Y`Ug&megQXl*_(9bYIJ&EI?4 z<{6#wsyN`Rm(X)iqc+z>{t)2zhvFSxF=&+~jVT2}MUt>N1#Jp}5Odvec;=RW>{4+j zoN>vfGk-{+!S^R8mepylU!c~Lz=0~;AuVE(sj5|r*?e|yfKcI)_|Pa_uV5Z8Vr95~ z2LpU5QYy;uQ5jgAZ%l-I`BysVZuJe%;x|#pn^}b@4B))bFEqeH1_WGKh?nt1v(yv9HZT#T?ZLE`*GtNiYR3FPCKYRL^sN ziQ?~VjMap-%y6vkJxuOjF$R|z4No~r&@6Q{o97FVHz}ftw^Q?ML_j;byR1JGRl)%> z^`ZJld#`kKdt4f5)L#?$jc^`7q3S|!Au%o$%^SCCJDyWs>i5H?j6DbIn~EhUE*@kF z(qwT+Dr3@BuWfeDoFJENQp(h~O9f$a2>J5|lN6AI?Wwwo)Cc{lH0+yXOtZ^fC34MCbr;x*j! zp2}#GeT9-JlE}ZNQ)T8tBtZdtHZ zsuHS>MpfC`)Uq-o^(^sDkvuKWBk7Fa^Fg3zP~1?BaxybxZF@>X3v~b6yDrM(EO1#C=dK?2chLIx6xJ-(Oi5gYp=3yk; z%5~8KOY0;HwowL;@#%%s%S^$dN4N7|!bZG5dnIGI?Nblt5T#(i-(I%!$4EsodON11 z!!k|e(a}rx%z??LyUN8O5*^FockZo!3V(1+Hl}T(v+vAu{LoLoSTcH-ZE#C^p4wr0eV%H4uz%S3nGh?aMO%!x<`AeRRZ; zI&M)h&XPw6I;#fme;DQ zwuMw-cQH&*wIVq6*+VJ*@N3;cFa*uPV(u>50A@I(d6Ege*K^`qH} zpjmX_;t8^x!THBw9!Ot+a6H>QgA1pAWaLk9bk9GqDkj= totalImagesCount) + if (opts.loadingCompleteCallback) opts.loadingCompleteCallback(); + }); + $(this).error(function() { + elementsLoaded++; + + if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount); + + // The image has errored + if (elementsLoaded >= totalImagesCount) + if (opts.loadingCompleteCallback) opts.loadingCompleteCallback(); + }); + } + }); + + // There are no unloaded images + if (totalImagesCount <= 0) + if (opts.loadingCompleteCallback) opts.loadingCompleteCallback(); +}; +})(jQuery); \ No newline at end of file diff --git a/public/js/showoff.js b/public/js/showoff.js index b20e6b7a8..8d35b5568 100644 --- a/public/js/showoff.js +++ b/public/js/showoff.js @@ -32,35 +32,41 @@ function setupPreso() { } function loadSlides() { - //load through #slides offscreen and copy back into #preso when prepared + //load slides offscreen, wait for images and then initialize $("#slides").load("/slides", false, function(){ - //center - centerSlides($('#slides > .slide')) - - //copy into presentation area - $("#preso").empty() - $('#slides > .slide').appendTo($("#preso")) - - //populate vars - slides = $('#preso > .slide') - slideTotal = slides.size() - - //setup jquery cycle with default show/hide transition - $('#preso').cycle({ - fx: 'none', - timeout: 0 - }); - - setupMenu() - if (slidesLoaded) { - showSlide() - alert('slides loaded') - } else { - showFirstSlide() - slidesLoaded = true - } - sh_highlightDocument('/js/sh_lang/', '.min.js') + $("#slides img").batchImageLoad({ + loadingCompleteCallback: initializePresentation + }) + }) +} + +function initializePresentation() { + //center slides offscreen + centerSlides($('#slides > .slide')) + + //copy into presentation area + $("#preso").empty() + $('#slides > .slide').appendTo($("#preso")) + + //populate vars + slides = $('#preso > .slide') + slideTotal = slides.size() + + //setup jquery cycle with default show/hide transition + $('#preso').cycle({ + fx: 'none', + timeout: 0 }) + + setupMenu() + if (slidesLoaded) { + showSlide() + alert('slides loaded') + } else { + showFirstSlide() + slidesLoaded = true + } + sh_highlightDocument('/js/sh_lang/', '.min.js') } function centerSlides(slides) { diff --git a/views/index.erb b/views/index.erb index 9b480bc17..d3d13f4d5 100644 --- a/views/index.erb +++ b/views/index.erb @@ -12,6 +12,7 @@ + From f56591ac03d0bc21b5976ed771a2fae9ae41e7ea Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Mon, 15 Mar 2010 22:41:10 +0000 Subject: [PATCH 07/12] added slide transitions - transition is selected through use of transition=tname on the !SLIDE definition - any transitions supported by jQuery Cycle plugin are supported, see http://www.malsup.com/jquery/cycle/browser.html - custom transitions can be added as per jQuery Cycle plugin, see http://www.malsup.com/jquery/cycle/adv2.html --- example/one/slidesA.md | 4 ++-- lib/showoff.rb | 17 +++++++++++++---- public/js/showoff.js | 7 +++---- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/example/one/slidesA.md b/example/one/slidesA.md index bb1b18c73..f0da64582 100644 --- a/example/one/slidesA.md +++ b/example/one/slidesA.md @@ -2,7 +2,7 @@ # First Slide # -!SLIDE bullets incremental +!SLIDE bullets incremental transition=fade # Second Slide # @@ -12,6 +12,6 @@ * a fourth thing * a fifth thing -!SLIDE center +!SLIDE center transition=scrollUp ![octocat](octocat.png) diff --git a/lib/showoff.rb b/lib/showoff.rb index 4ddb57d0c..58273cb6f 100644 --- a/lib/showoff.rb +++ b/lib/showoff.rb @@ -55,15 +55,24 @@ def process_markdown(name, content) end slides.each do |slide| md = '' + # extract content classes lines = slide.split("\n") - classes = lines.shift + content_classes = lines.shift.split slide = lines.join("\n") - md += '
' + # add content class too + content_classes.unshift "content" + # extract transition, defaulting to none + transition = 'none' + content_classes.delete_if { |x| x =~ /^transition=(.+)/ && transition = $1 } + puts "classes: #{content_classes.inspect}" + puts "transition: #{transition}" + # create html + md += "
" if seq - md += "
\n" + md += "
\n" seq += 1 else - md += "
\n" + md += "
\n" end sl = Markdown.new(slide).to_html sl = update_image_paths(name, sl) diff --git a/public/js/showoff.js b/public/js/showoff.js index 8d35b5568..b78893b24 100644 --- a/public/js/showoff.js +++ b/public/js/showoff.js @@ -52,9 +52,8 @@ function initializePresentation() { slides = $('#preso > .slide') slideTotal = slides.size() - //setup jquery cycle with default show/hide transition + //setup manual jquery cycle $('#preso').cycle({ - fx: 'none', timeout: 0 }) @@ -131,8 +130,8 @@ function showSlide(back_step) { } currentSlide = slides.eq(slidenum) - - $('#preso').cycle(slidenum) + var transition = currentSlide.attr('data-transition') + $('#preso').cycle(slidenum, transition) percent = getSlidePercent() $("#slideInfo").text((slidenum + 1) + '/' + slideTotal + ' - ' + percent + '%') From 57c554adc1caa198f0f32ef9483eae1b44b95e81 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Mon, 15 Mar 2010 22:43:16 +0000 Subject: [PATCH 08/12] modified jQueryCycle plugin to support transformation back to 'none' when stepping back through slides --- public/js/jquery.cycle.all.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/public/js/jquery.cycle.all.js b/public/js/jquery.cycle.all.js index 09ef3d9da..1d8441af9 100644 --- a/public/js/jquery.cycle.all.js +++ b/public/js/jquery.cycle.all.js @@ -886,8 +886,12 @@ $.fn.cycle.defaults = { // $.fn.cycle.transitions.none = function($cont, $slides, opts) { opts.fxFn = function(curr,next,opts,after){ + opts.cssBefore = { top: 0, left: 0 }; + $.fn.cycle.commonReset(curr,next,opts); + $(next).css(opts.cssBefore); $(next).show(); $(curr).hide(); + if (opts.cssAfter) $(curr).css(opts.cssAfter); after(); }; } From 2262f57bfdc02ebba5f1b36e13093a1f71067f39 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Mon, 15 Mar 2010 23:00:23 +0000 Subject: [PATCH 09/12] updated README to cover transitions --- README.txt | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/README.txt b/README.txt index d658e22df..38eabe076 100644 --- a/README.txt +++ b/README.txt @@ -20,10 +20,10 @@ It can: * re-enact command line interactions * call up a menu of sections/slides at any time to jump around * execute javascript or ruby live and display results + * do simple transitions (instant, fade, slide in) It might will can: - * do simple transitions (instant, fade, slide in) * show a timer - elapsed / remaining * perform simple animations of images moving between keyframes * show syncronized, hidden notes on another browser (like an iphone) @@ -68,7 +68,7 @@ the following contents: # My Presentation # - !SLIDE bullets incremental + !SLIDE bullets incremental transition=fade # Bullet Points # @@ -76,10 +76,10 @@ the following contents: * second point * third point -That represents two slides, one with just a large title and one with three -bullets that are incrementally updated when the slide is shown. In order for -ShowOff to see those slides, your showoff.json file needs to look something -like this: +That represents two slides, the first contains just a large title, and the +second is faded into view showing the title and three bullets that are then +incrementally shown. In order for ShowOff to see those slides, your +showoff.json file needs to look something like this: [ {"section":"one"} @@ -108,6 +108,43 @@ Some useful styles for each slide are: Check out the example directory included to see examples of most of these. +Transitions can be supplied through the use of transition=tname on the !SLIDE +definition, where tname is one of the following supported transitions: + + * blindX + * blindY + * blindZ + * cover + * curtainX + * curtainY + * fade + * fadeZoom + * growX + * growY + * none (this is the default) + * scrollUp + * scrollDown + * scrollLeft + * scrollRight + * scrollHorz + * scrollVert + * shuffle + * slideX + * slideY + * toss + * turnUp + * turnDown + * turnLeft + * turnRight + * uncover + * wipe + * zoom + +The transitions are provided by jQuery Cycle plugin. See +http://www.malsup.com/jquery/cycle/browser.html to view the effects and +http://www.malsup.com/jquery/cycle/adv2.html for how to add +custom effects. + You can manage the presentation with the following keys: * space, cursor right: next slide From 4ea3281e3633d941b246db335ac55943d54a5a0e Mon Sep 17 00:00:00 2001 From: Scott Chacon Date: Mon, 15 Mar 2010 16:28:22 -0700 Subject: [PATCH 10/12] some notes updates --- TODO.txt | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/TODO.txt b/TODO.txt index aab2433f1..ffeeb69e8 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,19 +1,13 @@ TODO ================= -- static output - - single html file - - pdf -- showoff.json in each subdir +- no transition on the back key +- can have showoff.json in each subdir - showoff add - add new slide/section - add slides of images directory (refactor script/import_images.rb) - simple highlighting (highlight region of slide / click to highlight) -- simple transitions - presenter tools - - show/hide timer - - warning when time is up or pace is too slow - - part of plugin system of things that can be running outside of slideshow - notes view (quick polling) - audience interface - slide download / git clone From c68eb590addf1719983b4f6c71c8f14578652b29 Mon Sep 17 00:00:00 2001 From: Kris Brown Date: Mon, 15 Mar 2010 23:44:34 +0000 Subject: [PATCH 11/12] no transition on the back key --- TODO.txt | 1 - public/js/showoff.js | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/TODO.txt b/TODO.txt index ffeeb69e8..2cbbc15b4 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,7 +1,6 @@ TODO ================= -- no transition on the back key - can have showoff.json in each subdir - showoff add - add new slide/section diff --git a/public/js/showoff.js b/public/js/showoff.js index b78893b24..f96b62d63 100644 --- a/public/js/showoff.js +++ b/public/js/showoff.js @@ -131,6 +131,9 @@ function showSlide(back_step) { currentSlide = slides.eq(slidenum) var transition = currentSlide.attr('data-transition') + if (back_step) { + transition = 'none' + } $('#preso').cycle(slidenum, transition) percent = getSlidePercent() From 0cc82277d63178f23b0033fdacaaf6d4a5c17fd7 Mon Sep 17 00:00:00 2001 From: Scott Chacon Date: Mon, 15 Mar 2010 19:41:33 -0700 Subject: [PATCH 12/12] updated gemspec to 0.1.1 release with krisb's changes --- showoff.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/showoff.gemspec b/showoff.gemspec index 50c5e532d..aeee7336f 100644 --- a/showoff.gemspec +++ b/showoff.gemspec @@ -1,7 +1,7 @@ Gem::Specification.new do |s| s.name = "showoff" - s.version = "0.1.0" - s.date = "2010-01-26" + s.version = "0.1.1" + s.date = "2010-03-15" s.summary = "The best damn presentation software a developer could ever love." s.homepage = "http://github.com/schacon/showoff" s.email = "schacon@gmail.com"