This repository has been archived on 2023-08-16. You can view files and clone it, but cannot push or open issues or pull requests.
Omphaloskepsis/plugins/jetpack/modules/shortcodes/js/jmpress.js
2018-03-21 18:19:20 +00:00

2722 lines
75 KiB
JavaScript

/*!
* jmpress.js v0.4.5
* http://jmpressjs.github.com/jmpress.js
*
* A jQuery plugin to build a website on the infinite canvas.
*
* Copyright 2013 Kyle Robinson Young @shama & Tobias Koppers @sokra
* Licensed MIT
* http://www.opensource.org/licenses/mit-license.php
*
* Based on the foundation laid by Bartek Szopka @bartaz
*//*!
* jmpress.js v0.4.5
* http://jmpressjs.github.com/jmpress.js
*
* A jQuery plugin to build a website on the infinite canvas.
*
* Copyright 2013 Kyle Robinson Young @shama & Tobias Koppers @sokra
* Licensed MIT
* http://www.opensource.org/licenses/mit-license.php
*
* Based on the foundation laid by Bartek Szopka @bartaz
*//*
* core.js
* The core of jmpress.js
*/
(function( $, document, window, undefined ) {
'use strict';
/**
* Set supported prefixes
*
* @access protected
* @return Function to get prefixed property
*/
var pfx = (function () {
var style = document.createElement('dummy').style,
prefixes = 'Webkit Moz O ms Khtml'.split(' '),
memory = {};
return function ( prop ) {
if ( typeof memory[ prop ] === "undefined" ) {
var ucProp = prop.charAt(0).toUpperCase() + prop.substr(1),
props = (prop + ' ' + prefixes.join(ucProp + ' ') + ucProp).split(' ');
memory[ prop ] = null;
for ( var i in props ) {
if ( style[ props[i] ] !== undefined ) {
memory[ prop ] = props[i];
break;
}
}
}
return memory[ prop ];
};
}());
/**
* map ex. "WebkitTransform" to "-webkit-transform"
*/
function mapProperty( name ) {
if(!name) {
return;
}
var index = 1 + name.substr(1).search(/[A-Z]/);
var prefix = name.substr(0, index).toLowerCase();
var postfix = name.substr(index).toLowerCase();
return "-" + prefix + "-" + postfix;
}
function addComma( attribute ) {
if(!attribute) {
return "";
}
return attribute + ",";
}
/**
* Return an jquery object only if it's not empty
*/
function ifNotEmpty(el) {
if(el.length > 0) {
return el;
}
return null;
}
/**
* Default Settings
*/
var defaults = {
/* CLASSES */
stepSelector: '.step'
,containerClass: ''
,canvasClass: ''
,areaClass: ''
,notSupportedClass: 'not-supported'
/* CONFIG */
,fullscreen: true
/* ANIMATION */
,animation: {
transformOrigin: 'top left'
,transitionProperty: addComma(mapProperty(pfx('transform'))) + addComma(mapProperty(pfx('perspective'))) + 'opacity'
,transitionDuration: '1s'
,transitionDelay: '500ms'
,transitionTimingFunction: 'ease-in-out'
,transformStyle: "preserve-3d"
}
,transitionDuration: 1500
};
var callbacks = {
'beforeChange': 1
,'beforeInitStep': 1
,'initStep': 1
,'beforeInit': 1
,'afterInit': 1
,'beforeDeinit': 1
,'afterDeinit': 1
,'applyStep': 1
,'unapplyStep': 1
,'setInactive': 1
,'beforeActive': 1
,'setActive': 1
,'selectInitialStep': 1
,'selectPrev': 1
,'selectNext': 1
,'selectHome': 1
,'selectEnd': 1
,'idle': 1
,'applyTarget': 1
};
for(var callbackName in callbacks) {
defaults[callbackName] = [];
}
/**
* Initialize jmpress
*/
function init( args ) {
args = $.extend(true, {}, args || {});
// accept functions and arrays of functions as callbacks
var callbackArgs = {};
var callbackName = null;
for (callbackName in callbacks) {
callbackArgs[callbackName] = $.isFunction( args[callbackName] ) ?
[ args[callbackName] ] :
args[callbackName];
args[callbackName] = [];
}
// MERGE SETTINGS
var settings = $.extend(true, {}, defaults, args);
for (callbackName in callbacks) {
if (callbackArgs[callbackName]) {
Array.prototype.push.apply(settings[callbackName], callbackArgs[callbackName]);
}
}
/*** MEMBER VARS ***/
var jmpress = $( this )
,container = null
,area = null
,oldStyle = {
container: ""
,area: ""
}
,canvas = null
,current = null
,active = false
,activeSubstep = null
,activeDelegated = false;
/*** MEMBER FUNCTIONS ***/
// functions have to be called with this
/**
* Init a single step
*
* @param element the element of the step
* @param idx number of step
*/
function doStepInit( element, idx ) {
var data = dataset( element );
var step = {
oldStyle: $(element).attr("style") || ""
};
var callbackData = {
data: data
,stepData: step
};
callCallback.call(this, 'beforeInitStep', $(element), callbackData);
step.delegate = data.delegate;
callCallback.call(this, 'initStep', $(element), callbackData);
$(element).data('stepData', step);
if ( !$(element).attr('id') ) {
$(element).attr('id', 'step-' + (idx + 1));
}
callCallback.call(this, 'applyStep', $(element), callbackData);
}
/**
* Deinit a single step
*
* @param element the element of the step
*/
function doStepDeinit( element ) {
var stepData = $(element).data('stepData');
$(element).attr("style", stepData.oldStyle);
callCallback.call(this, 'unapplyStep', $(element), {
stepData: stepData
});
}
/**
* Reapplies stepData to the element
*
* @param element
*/
function doStepReapply( element ) {
callCallback.call(this, 'unapplyStep', $(element), {
stepData: element.data("stepData")
});
callCallback.call(this, 'applyStep', $(element), {
stepData: element.data("stepData")
});
}
/**
* Completly deinit jmpress
*
*/
function deinit() {
if ( active ) {
callCallback.call(this, 'setInactive', active, {
stepData: $(active).data('stepData')
,reason: "deinit"
} );
}
if (current.jmpressClass) {
$(jmpress).removeClass(current.jmpressClass);
}
callCallback.call(this, 'beforeDeinit', $(this), {});
$(settings.stepSelector, jmpress).each(function( idx ) {
doStepDeinit.call(jmpress, this );
});
container.attr("style", oldStyle.container);
if(settings.fullscreen) {
$("html").attr("style", "");
}
area.attr("style", oldStyle.area);
$(canvas).children().each(function() {
jmpress.append( $( this ) );
});
if( settings.fullscreen ) {
canvas.remove();
} else {
canvas.remove();
area.remove();
}
callCallback.call(this, 'afterDeinit', $(this), {});
$(jmpress).data("jmpressmethods", false);
}
/**
* Call a callback
*
* @param callbackName String callback which should be called
* @param element some arguments to the callback
* @param eventData
*/
function callCallback( callbackName, element, eventData ) {
eventData.settings = settings;
eventData.current = current;
eventData.container = container;
eventData.parents = element ? getStepParents(element) : null;
eventData.current = current;
eventData.jmpress = this;
var result = {};
$.each( settings[callbackName], function(idx, callback) {
result.value = callback.call( jmpress, element, eventData ) || result.value;
});
return result.value;
}
/**
*
*/
function getStepParents( el ) {
return $(el).parentsUntil(jmpress).not(jmpress).filter(settings.stepSelector);
}
/**
* Reselect the active step
*
* @param String type reason of reselecting step
*/
function reselect( type ) {
return select( { step: active, substep: activeSubstep }, type);
}
/**
* Select a given step
*
* @param el element to select
* @param type reason of changing step
* @return Object element selected
*/
function select( el, type ) {
var substep;
if ( $.isPlainObject( el ) ) {
substep = el.substep;
el = el.step;
}
if ( typeof el === 'string') {
el = jmpress.find( el ).first();
}
if ( !el || !$(el).data('stepData') ) {
return false;
}
scrollFix.call(this);
var step = $(el).data('stepData');
var cancelSelect = false;
callCallback.call(this, "beforeChange", el, {
stepData: step
,reason: type
,cancel: function() {
cancelSelect = true;
}
});
if (cancelSelect) {
return undefined;
}
var target = {};
var delegated = el;
if($(el).data("stepData").delegate) {
delegated = ifNotEmpty($(el).parentsUntil(jmpress).filter(settings.stepSelector).filter(step.delegate)) ||
ifNotEmpty($(el).near(step.delegate)) ||
ifNotEmpty($(el).near(step.delegate, true)) ||
ifNotEmpty($(step.delegate, jmpress));
if(delegated) {
step = delegated.data("stepData");
} else {
// Do not delegate if expression not found
delegated = el;
}
}
if ( activeDelegated ) {
callCallback.call(this, 'setInactive', activeDelegated, {
stepData: $(activeDelegated).data('stepData')
,delegatedFrom: active
,reason: type
,target: target
,nextStep: delegated
,nextSubstep: substep
,nextStepData: step
} );
}
var callbackData = {
stepData: step
,delegatedFrom: el
,reason: type
,target: target
,substep: substep
,prevStep: activeDelegated
,prevSubstep: activeSubstep
,prevStepData: activeDelegated && $(activeDelegated).data('stepData')
};
callCallback.call(this, 'beforeActive', delegated, callbackData);
callCallback.call(this, 'setActive', delegated, callbackData);
// Set on step class on root element
if (current.jmpressClass) {
$(jmpress).removeClass(current.jmpressClass);
}
$(jmpress).addClass(current.jmpressClass = 'step-' + $(delegated).attr('id') );
if (current.jmpressDelegatedClass) {
$(jmpress).removeClass(current.jmpressDelegatedClass);
}
$(jmpress).addClass(current.jmpressDelegatedClass = 'delegating-step-' + $(el).attr('id') );
callCallback.call(this, "applyTarget", delegated, $.extend({
canvas: canvas
,area: area
,beforeActive: activeDelegated
}, callbackData));
active = el;
activeSubstep = callbackData.substep;
activeDelegated = delegated;
if(current.idleTimeout) {
clearTimeout(current.idleTimeout);
}
current.idleTimeout = setTimeout(function() {
callCallback.call(this, 'idle', delegated, callbackData);
}, Math.max(1, settings.transitionDuration - 100));
return delegated;
}
/**
* This should fix ANY kind of buggy scrolling
*/
function scrollFix() {
(function fix() {
if ($(container)[0].tagName === "BODY") {
try {
window.scrollTo(0, 0);
} catch(e) {}
}
$(container).scrollTop(0);
$(container).scrollLeft(0);
function check() {
if ($(container).scrollTop() !== 0 ||
$(container).scrollLeft() !== 0) {
fix();
}
}
setTimeout(check, 1);
setTimeout(check, 10);
setTimeout(check, 100);
setTimeout(check, 200);
setTimeout(check, 400);
}());
}
/**
* Alias for select
*/
function goTo( el ) {
return select.call(this, el, "jump" );
}
/**
* Goto Next Slide
*
* @return Object newly active slide
*/
function next() {
return select.call(this, callCallback.call(this, 'selectNext', active, {
stepData: $(active).data('stepData')
,substep: activeSubstep
}), "next" );
}
/**
* Goto Previous Slide
*
* @return Object newly active slide
*/
function prev() {
return select.call(this, callCallback.call(this, 'selectPrev', active, {
stepData: $(active).data('stepData')
,substep: activeSubstep
}), "prev" );
}
/**
* Goto First Slide
*
* @return Object newly active slide
*/
function home() {
return select.call(this, callCallback.call(this, 'selectHome', active, {
stepData: $(active).data('stepData')
}), "home" );
}
/**
* Goto Last Slide
*
* @return Object newly active slide
*/
function end() {
return select.call(this, callCallback.call(this, 'selectEnd', active, {
stepData: $(active).data('stepData')
}), "end" );
}
/**
* Manipulate the canvas
*
* @param props
* @return Object
*/
function canvasMod( props ) {
css(canvas, props || {});
return $(canvas);
}
/**
* Return current step
*
* @return Object
*/
function getActive() {
return activeDelegated && $(activeDelegated);
}
/**
* fire a callback
*
* @param callbackName
* @param element
* @param eventData
* @return void
*/
function fire( callbackName, element, eventData ) {
if( !callbacks[callbackName] ) {
$.error( "callback " + callbackName + " is not registered." );
} else {
return callCallback.call(this, callbackName, element, eventData);
}
}
/**
* PUBLIC METHODS LIST
*/
jmpress.data("jmpressmethods", {
select: select
,reselect: reselect
,scrollFix: scrollFix
,goTo: goTo
,next: next
,prev: prev
,home: home
,end: end
,canvas: canvasMod
,container: function() { return container; }
,settings: function() { return settings; }
,active: getActive
,current: function() { return current; }
,fire: fire
,init: function(step) {
doStepInit.call(this, $(step), current.nextIdNumber++);
}
,deinit: function(step) {
if(step) {
doStepDeinit.call(this, $(step));
} else {
deinit.call(this);
}
}
,reapply: doStepReapply
});
/**
* Check for support
* This will be removed in near future, when support is coming
*
* @access protected
* @return void
*/
function checkSupport() {
var ua = navigator.userAgent.toLowerCase();
return (ua.search(/(iphone)|(ipod)|(android)/) === -1) || (ua.search(/(chrome)/) !== -1);
}
// BEGIN INIT
// CHECK FOR SUPPORT
if (checkSupport() === false) {
if (settings.notSupportedClass) {
jmpress.addClass(settings.notSupportedClass);
}
return;
} else {
if (settings.notSupportedClass) {
jmpress.removeClass(settings.notSupportedClass);
}
}
// grabbing all steps
var steps = $(settings.stepSelector, jmpress);
// GERNERAL INIT OF FRAME
container = jmpress;
area = $('<div />');
canvas = $('<div />');
$(jmpress).children().filter(steps).each(function() {
canvas.append( $( this ) );
});
if(settings.fullscreen) {
container = $('body');
$("html").css({
overflow: 'hidden'
});
area = jmpress;
}
oldStyle.area = area.attr("style") || "";
oldStyle.container = container.attr("style") || "";
if(settings.fullscreen) {
container.css({
height: '100%'
});
jmpress.append( canvas );
} else {
container.css({
position: "relative"
});
area.append( canvas );
jmpress.append( area );
}
$(container).addClass(settings.containerClass);
$(area).addClass(settings.areaClass);
$(canvas).addClass(settings.canvasClass);
document.documentElement.style.height = "100%";
container.css({
overflow: 'hidden'
});
var props = {
position: "absolute"
,transitionDuration: '0s'
};
props = $.extend({}, settings.animation, props);
css(area, props);
css(area, {
top: '50%'
,left: '50%'
,perspective: '1000px'
});
css(canvas, props);
current = {};
callCallback.call(this, 'beforeInit', null, {});
// INITIALIZE EACH STEP
steps.each(function( idx ) {
doStepInit.call(jmpress, this, idx );
});
current.nextIdNumber = steps.length;
callCallback.call(this, 'afterInit', null, {});
// START
select.call(this, callCallback.call(this, 'selectInitialStep', "init", {}) );
if (settings.initClass) {
$(steps).removeClass(settings.initClass);
}
}
/**
* Return default settings
*
* @return Object
*/
function getDefaults() {
return defaults;
}
/**
* Register a callback or a jmpress function
*
* @access public
* @param name String the name of the callback or function
* @param func Function? the function to be added
*/
function register(name, func) {
if( $.isFunction(func) ) {
if( methods[name] ) {
$.error( "function " + name + " is already registered." );
} else {
methods[name] = func;
}
} else {
if( callbacks[name] ) {
$.error( "callback " + name + " is already registered." );
} else {
callbacks[name] = 1;
defaults[name] = [];
}
}
}
/**
* Set CSS on element w/ prefixes
*
* @return Object element which properties were set
*
* TODO: Consider bypassing pfx and blindly set as jQuery
* already checks for support
*/
function css( el, props ) {
var key, pkey, cssObj = {};
for ( key in props ) {
if ( props.hasOwnProperty(key) ) {
pkey = pfx(key);
if ( pkey !== null ) {
cssObj[pkey] = props[key];
}
}
}
$(el).css(cssObj);
return el;
}
/**
* Return dataset for element
*
* @param el element
* @return Object
*/
function dataset( el ) {
if ( $(el)[0].dataset ) {
return $.extend({}, $(el)[0].dataset);
}
function toCamelcase( str ) {
str = str.split( '-' );
for( var i = 1; i < str.length; i++ ) {
str[i] = str[i].substr(0, 1).toUpperCase() + str[i].substr(1);
}
return str.join( '' );
}
var returnDataset = {};
var attrs = $(el)[0].attributes;
$.each(attrs, function ( idx, attr ) {
if ( attr.nodeName.substr(0, 5) === "data-" ) {
returnDataset[ toCamelcase(attr.nodeName.substr(5)) ] = attr.nodeValue;
}
});
return returnDataset;
}
/**
* Returns true, if jmpress is initialized
*
* @return bool
*/
function initialized() {
return !!$(this).data("jmpressmethods");
}
/**
* PUBLIC STATIC METHODS LIST
*/
var methods = {
init: init
,initialized: initialized
,deinit: function() {}
,css: css
,pfx: pfx
,defaults: getDefaults
,register: register
,dataset: dataset
};
/**
* $.jmpress()
*/
$.fn.jmpress = function( method ) {
function f() {
var jmpressmethods = $(this).data("jmpressmethods");
if ( jmpressmethods && jmpressmethods[method] ) {
return jmpressmethods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( callbacks[method] && jmpressmethods ) {
var settings = jmpressmethods.settings();
var func = Array.prototype.slice.call( arguments, 1 )[0];
if ($.isFunction( func )) {
settings[method] = settings[method] || [];
settings[method].push(func);
}
} else if ( typeof method === 'object' || ! method ) {
return init.apply( this, arguments );
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.jmpress' );
}
// to allow chaining
return this;
}
var args = arguments;
var result;
$(this).each(function(idx, element) {
result = f.apply(element, args);
});
return result;
};
$.extend({
jmpress: function( method ) {
if ( methods[method] ) {
return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ));
} else if ( callbacks[method] ) {
// plugin interface
var func = Array.prototype.slice.call( arguments, 1 )[0];
if ($.isFunction( func )) {
defaults[method].push(func);
} else {
$.error( 'Second parameter should be a function: $.jmpress( callbackName, callbackFunction )' );
}
} else {
$.error( 'Method ' + method + ' does not exist on jQuery.jmpress' );
}
}
});
}(jQuery, document, window));
/*
* near.js
* Find steps near each other
*/
(function( $, document, window, undefined ) {
'use strict';
// add near( selector, backwards = false) to jquery
function checkAndGo( elements, func, selector, backwards ) {
var next;
elements.each(function(idx, element) {
if(backwards) {
next = func(element, selector, backwards);
if (next) {
return false;
}
}
if( $(element).is(selector) ) {
next = element;
return false;
}
if(!backwards) {
next = func(element, selector, backwards);
if (next) {
return false;
}
}
});
return next;
}
function findNextInChildren(item, selector, backwards) {
var children = $(item).children();
if(backwards) {
children = $(children.get().reverse());
}
return checkAndGo( children, findNextInChildren, selector, backwards );
}
function findNextInSiblings(item, selector, backwards) {
return checkAndGo(
$(item)[backwards ? "prevAll" : "nextAll"](),
findNextInChildren, selector, backwards );
}
function findNextInParents(item, selector, backwards) {
var next;
var parents = $(item).parents();
parents = $(parents.get());
$.each(parents.get(), function(idx, element) {
if( backwards && $(element).is(selector) ) {
next = element;
return false;
}
next = findNextInSiblings(element, selector, backwards);
if(next) {
return false;
}
});
return next;
}
$.fn.near = function( selector, backwards ) {
var array = [];
$(this).each(function(idx, element) {
var near = (backwards ?
false :
findNextInChildren( element, selector, backwards )) ||
findNextInSiblings( element, selector, backwards ) ||
findNextInParents( element, selector, backwards );
if( near ) {
array.push(near);
}
});
return $(array);
};
}(jQuery, document, window));
/*
* transform.js
* The engine that powers the transforms or falls back to other methods
*/
(function( $, document, window, undefined ) {
'use strict';
/* FUNCTIONS */
function toCssNumber(number) {
return (Math.round(10000*number)/10000)+"";
}
/**
* 3D and 2D engines
*/
var engines = {
3: {
transform: function( el, data ) {
var transform = 'translate(-50%,-50%)';
$.each(data, function(idx, item) {
var coord = ["X", "Y", "Z"];
var i;
if(item[0] === "translate") { // ["translate", x, y, z]
transform += " translate3d(" + toCssNumber(item[1] || 0) + "px," + toCssNumber(item[2] || 0) + "px," + toCssNumber(item[3] || 0) + "px)";
} else if(item[0] === "rotate") {
var order = item[4] ? [1, 2, 3] : [3, 2, 1];
for(i = 0; i < 3; i++) {
transform += " rotate" + coord[order[i]-1] + "(" + toCssNumber(item[order[i]] || 0) + "deg)";
}
} else if(item[0] === "scale") {
for(i = 0; i < 3; i++) {
transform += " scale" + coord[i] + "(" + toCssNumber(item[i+1] || 1) + ")";
}
}
});
$.jmpress("css", el, $.extend({}, { transform: transform }));
}
}
,2: {
transform: function( el, data ) {
var transform = 'translate(-50%,-50%)';
$.each(data, function(idx, item) {
var coord = ["X", "Y"];
if(item[0] === "translate") { // ["translate", x, y, z]
transform += " translate(" + toCssNumber(item[1] || 0) + "px," + toCssNumber(item[2] || 0) + "px)";
} else if(item[0] === "rotate") {
transform += " rotate(" + toCssNumber(item[3] || 0) + "deg)";
} else if(item[0] === "scale") {
for(var i = 0; i < 2; i++) {
transform += " scale" + coord[i] + "(" + toCssNumber(item[i+1] || 1) + ")";
}
}
});
$.jmpress("css", el, $.extend({}, { transform: transform }));
}
}
,1: {
// CHECK IF SUPPORT IS REALLY NEEDED?
// this not even work without scaling...
// it may better to display the normal view
transform: function( el, data ) {
var anitarget = { top: 0, left: 0 };
$.each(data, function(idx, item) {
var coord = ["X", "Y"];
if(item[0] === "translate") { // ["translate", x, y, z]
anitarget.left = Math.round(item[1] || 0) + "px";
anitarget.top = Math.round(item[2] || 0) + "px";
}
});
el.animate(anitarget, 1000); // TODO: Use animation duration
}
}
};
/**
* Engine to power cross-browser translate, scale and rotate.
*/
var engine = (function() {
if ($.jmpress("pfx", "perspective")) {
return engines[3];
} else if ($.jmpress("pfx", "transform")) {
return engines[2];
} else {
// CHECK IF SUPPORT IS REALLY NEEDED?
return engines[1];
}
}());
$.jmpress("defaults").reasonableAnimation = {};
$.jmpress("initStep", function( step, eventData ) {
var data = eventData.data;
var stepData = eventData.stepData;
var pf = parseFloat;
$.extend(stepData, {
x: pf(data.x) || 0
,y: pf(data.y) || 0
,z: pf(data.z) || 0
,r: pf(data.r) || 0
,phi: pf(data.phi) || 0
,rotate: pf(data.rotate) || 0
,rotateX: pf(data.rotateX) || 0
,rotateY: pf(data.rotateY) || 0
,rotateZ: pf(data.rotateZ) || 0
,revertRotate: false
,scale: pf(data.scale) || 1
,scaleX: pf(data.scaleX) || false
,scaleY: pf(data.scaleY) || false
,scaleZ: pf(data.scaleZ) || 1
});
});
$.jmpress("afterInit", function( nil, eventData ) {
var stepSelector = eventData.settings.stepSelector,
current = eventData.current;
current.perspectiveScale = 1;
current.maxNestedDepth = 0;
var nestedSteps = $(eventData.jmpress).find(stepSelector).children(stepSelector);
while(nestedSteps.length) {
current.maxNestedDepth++;
nestedSteps = nestedSteps.children(stepSelector);
}
});
$.jmpress("applyStep", function( step, eventData ) {
$.jmpress("css", $(step), {
position: "absolute"
,transformStyle: "preserve-3d"
});
if ( eventData.parents.length > 0 ) {
$.jmpress("css", $(step), {
top: "50%"
,left: "50%"
});
}
var sd = eventData.stepData;
var transform = [
["translate",
sd.x || (sd.r * Math.sin(sd.phi*Math.PI/180)),
sd.y || (-sd.r * Math.cos(sd.phi*Math.PI/180)),
sd.z],
["rotate",
sd.rotateX,
sd.rotateY,
sd.rotateZ || sd.rotate,
true],
["scale",
sd.scaleX || sd.scale,
sd.scaleY || sd.scale,
sd.scaleZ || sd.scale]
];
engine.transform( step, transform );
});
$.jmpress("setActive", function( element, eventData ) {
var target = eventData.target;
var step = eventData.stepData;
var tf = target.transform = [];
target.perspectiveScale = 1;
for(var i = eventData.current.maxNestedDepth; i > (eventData.parents.length || 0); i--) {
tf.push(["scale"], ["rotate"], ["translate"]);
}
tf.push(["scale",
1 / (step.scaleX || step.scale),
1 / (step.scaleY || step.scale),
1 / (step.scaleZ)]);
tf.push(["rotate",
-step.rotateX,
-step.rotateY,
-(step.rotateZ || step.rotate)]);
tf.push(["translate",
-(step.x || (step.r * Math.sin(step.phi*Math.PI/180))),
-(step.y || (-step.r * Math.cos(step.phi*Math.PI/180))),
-step.z]);
target.perspectiveScale *= (step.scaleX || step.scale);
$.each(eventData.parents, function(idx, element) {
var step = $(element).data("stepData");
tf.push(["scale",
1 / (step.scaleX || step.scale),
1 / (step.scaleY || step.scale),
1 / (step.scaleZ)]);
tf.push(["rotate",
-step.rotateX,
-step.rotateY,
-(step.rotateZ || step.rotate)]);
tf.push(["translate",
-(step.x || (step.r * Math.sin(step.phi*Math.PI/180))),
-(step.y || (-step.r * Math.cos(step.phi*Math.PI/180))),
-step.z]);
target.perspectiveScale *= (step.scaleX || step.scale);
});
$.each(tf, function(idx, item) {
if(item[0] !== "rotate") {
return;
}
function lowRotate(name) {
if(eventData.current["rotate"+name+"-"+idx] === undefined) {
eventData.current["rotate"+name+"-"+idx] = item[name] || 0;
}
var cur = eventData.current["rotate"+name+"-"+idx], tar = item[name] || 0,
curmod = cur % 360, tarmod = tar % 360;
if(curmod < 0) {
curmod += 360;
}
if(tarmod < 0) {
tarmod += 360;
}
var diff = tarmod - curmod;
if(diff < -180) {
diff += 360;
} else if(diff > 180) {
diff -= 360;
}
eventData.current["rotate"+name+"-"+idx] = item[name] = cur + diff;
}
lowRotate(1);
lowRotate(2);
lowRotate(3);
});
});
$.jmpress("applyTarget", function( active, eventData ) {
var target = eventData.target,
props, step = eventData.stepData,
settings = eventData.settings,
zoomin = target.perspectiveScale * 1.3 < eventData.current.perspectiveScale,
zoomout = target.perspectiveScale > eventData.current.perspectiveScale * 1.3;
// extract first scale from transform
var lastScale = -1;
$.each(target.transform, function(idx, item) {
if(item.length <= 1) {
return;
}
if(item[0] === "rotate" &&
item[1] % 360 === 0 &&
item[2] % 360 === 0 &&
item[3] % 360 === 0) {
return;
}
if(item[0] === "scale") {
lastScale = idx;
} else {
return false;
}
});
if(lastScale !== eventData.current.oldLastScale) {
zoomin = zoomout = false;
eventData.current.oldLastScale = lastScale;
}
var extracted = [];
if(lastScale !== -1) {
while(lastScale >= 0) {
if(target.transform[lastScale][0] === "scale") {
extracted.push(target.transform[lastScale]);
target.transform[lastScale] = ["scale"];
}
lastScale--;
}
}
var animation = settings.animation;
if(settings.reasonableAnimation[eventData.reason]) {
animation = $.extend({},
animation,
settings.reasonableAnimation[eventData.reason]);
}
props = {
// to keep the perspective look similar for different scales
// we need to 'scale' the perspective, too
perspective: Math.round(target.perspectiveScale * 1000) + "px"
};
props = $.extend({}, animation, props);
if (!zoomin) {
props.transitionDelay = '0s';
}
if (!eventData.beforeActive) {
props.transitionDuration = '0s';
props.transitionDelay = '0s';
}
$.jmpress("css", eventData.area, props);
engine.transform(eventData.area, extracted);
props = $.extend({}, animation);
if (!zoomout) {
props.transitionDelay = '0s';
}
if (!eventData.beforeActive) {
props.transitionDuration = '0s';
props.transitionDelay = '0s';
}
eventData.current.perspectiveScale = target.perspectiveScale;
$.jmpress("css", eventData.canvas, props);
engine.transform(eventData.canvas, target.transform);
});
}(jQuery, document, window));
/*
* active.js
* Set the active classes on steps
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress;
/* DEFINES */
var activeClass = 'activeClass',
nestedActiveClass = 'nestedActiveClass';
/* DEFAULTS */
var defaults = $jmpress( 'defaults' );
defaults[nestedActiveClass] = "nested-active";
defaults[activeClass] = "active";
/* HOOKS */
$jmpress( 'setInactive', function( step, eventData ) {
var settings = eventData.settings,
activeClassSetting = settings[activeClass],
nestedActiveClassSettings = settings[nestedActiveClass];
if(activeClassSetting) {
$(step).removeClass( activeClassSetting );
}
if(nestedActiveClassSettings) {
$.each(eventData.parents, function(idx, element) {
$(element).removeClass(nestedActiveClassSettings);
});
}
});
$jmpress( 'setActive', function( step, eventData ) {
var settings = eventData.settings,
activeClassSetting = settings[activeClass],
nestedActiveClassSettings = settings[nestedActiveClass];
if(activeClassSetting) {
$(step).addClass( activeClassSetting );
}
if(nestedActiveClassSettings) {
$.each(eventData.parents, function(idx, element) {
$(element).addClass(nestedActiveClassSettings);
});
}
});
}(jQuery, document, window));
/*
* circular.js
* Repeat from start after end
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress;
/* FUNCTIONS */
function firstSlide( step, eventData ) {
return $(this).find(eventData.settings.stepSelector).first();
}
function prevOrNext( jmpress, step, eventData, prev) {
if (!step) {
return false;
}
var stepSelector = eventData.settings.stepSelector;
step = $(step);
do {
var item = step.near( stepSelector, prev );
if (item.length === 0 || item.closest(jmpress).length === 0) {
item = $(jmpress).find(stepSelector)[prev?"last":"first"]();
}
if (!item.length) {
return false;
}
step = item;
} while( step.data("stepData").exclude );
return step;
}
/* HOOKS */
$jmpress( 'initStep', function( step, eventData ) {
eventData.stepData.exclude = eventData.data.exclude && ["false", "no"].indexOf(eventData.data.exclude) === -1;
});
$jmpress( 'selectInitialStep', firstSlide);
$jmpress( 'selectHome', firstSlide);
$jmpress( 'selectEnd', function( step, eventData ) {
return $(this).find(eventData.settings.stepSelector).last();
});
$jmpress( 'selectPrev', function( step, eventData ) {
return prevOrNext(this, step, eventData, true);
});
$jmpress( 'selectNext', function( step, eventData ) {
return prevOrNext(this, step, eventData);
});
}(jQuery, document, window));
/*
* start.js
* Set the first step to start on
*/
(function( $, document, window, undefined ) {
'use strict';
/* HOOKS */
$.jmpress( 'selectInitialStep', function( nil, eventData ) {
return eventData.settings.start;
});
}(jQuery, document, window));
/*
* ways.js
* Control the flow of the steps
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress;
/* FUNCTIONS */
function routeFunc( jmpress, route, type ) {
for(var i = 0; i < route.length - 1; i++) {
var from = route[i];
var to = route[i+1];
if($(jmpress).jmpress("initialized")) {
$(from, jmpress).data("stepData")[type] = to;
} else {
$(from, jmpress).attr('data-' + type, to);
}
}
}
function selectPrevOrNext( step, eventData, attr, prev ) {
var stepData = eventData.stepData;
if(stepData[attr]) {
var near = $(step).near(stepData[attr], prev);
if(near && near.length) {
return near;
}
near = $(stepData[attr], this)[prev?"last":"first"]();
if(near && near.length) {
return near;
}
}
}
/* EXPORTED FUNCTIONS */
$jmpress( 'register', 'route', function( route, unidirectional, reversedRoute ) {
if( typeof route === "string" ) {
route = [route, route];
}
routeFunc(this, route, reversedRoute ? "prev" : "next");
if (!unidirectional) {
routeFunc(this, route.reverse(), reversedRoute ? "next" : "prev");
}
});
/* HOOKS */
$jmpress( 'initStep', function( step, eventData ) {
for(var attr in {next:1,prev:1}) {
eventData.stepData[attr] = eventData.data[attr];
}
});
$jmpress( 'selectNext', function( step, eventData ) {
return selectPrevOrNext.call(this, step, eventData, "next");
});
$jmpress( 'selectPrev', function( step, eventData ) {
return selectPrevOrNext.call(this, step, eventData, "prev", true);
});
}(jQuery, document, window));
/*
* ajax.js
* Load steps via ajax
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress;
/* DEFINES */
var afterStepLoaded = 'ajax:afterStepLoaded',
loadStep = 'ajax:loadStep';
/* REGISTER EVENTS */
$jmpress('register', loadStep);
$jmpress('register', afterStepLoaded);
/* DEFAULTS */
$jmpress('defaults').ajaxLoadedClass = "loaded";
/* HOOKS */
$jmpress('initStep', function( step, eventData ) {
eventData.stepData.src = $(step).attr('href') || eventData.data.src || false;
eventData.stepData.srcLoaded = false;
});
$jmpress(loadStep, function( step, eventData ) {
var stepData = eventData.stepData,
href = stepData && stepData.src,
settings = eventData.settings;
if ( href ) {
$(step).addClass( settings.ajaxLoadedClass );
stepData.srcLoaded = true;
$(step).load(href, function(response, status, xhr) {
$(eventData.jmpress).jmpress('fire', afterStepLoaded, step, $.extend({}, eventData, {
response: response
,status: status
,xhr: xhr
}));
});
}
});
$jmpress('idle', function( step, eventData ) {
if (!step) {
return;
}
var settings = eventData.settings,
jmpress = $(this),
stepData = eventData.stepData;
var siblings = $(step)
.add( $(step).near( settings.stepSelector ) )
.add( $(step).near( settings.stepSelector, true) )
.add( jmpress.jmpress('fire', 'selectPrev', step, {
stepData: $(step).data('stepData')
}))
.add( jmpress.jmpress('fire', 'selectNext', step, {
stepData: $(step).data('stepData')
}));
siblings.each(function() {
var step = this,
stepData = $(step).data("stepData");
if(!stepData.src || stepData.srcLoaded) {
return;
}
jmpress.jmpress('fire', loadStep, step, {
stepData: $(step).data('stepData')
});
});
});
$jmpress("setActive", function(step, eventData) {
var stepData = $(step).data("stepData");
if(!stepData.src || stepData.srcLoaded) {
return;
}
$(this).jmpress('fire', loadStep, step, {
stepData: $(step).data('stepData')
});
});
}(jQuery, document, window));
/*
* hash.js
* Detect and set the URL hash
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress,
hashLink = "a[href^=#]";
/* FUNCTIONS */
function randomString() {
return "" + Math.round(Math.random() * 100000, 0);
}
/**
* getElementFromUrl
*
* @return String or undefined
*/
function getElementFromUrl(settings) {
// get id from url # by removing `#` or `#/` from the beginning,
// so both "fallback" `#slide-id` and "enhanced" `#/slide-id` will work
// TODO SECURITY check user input to be valid!
try {
var el = $( '#' + window.location.hash.replace(/^#\/?/,"") );
return el.length > 0 && el.is(settings.stepSelector) ? el : undefined;
} catch(e) {}
}
function setHash(stepid) {
var shouldBeHash = "#/" + stepid;
if(window.history && window.history.pushState) {
// shouldBeHash = "#" + stepid;
// consider this for future versions
// it has currently issues, when startup with a link with hash (webkit)
if(window.location.hash !== shouldBeHash) {
window.history.pushState({}, '', shouldBeHash);
}
} else {
if(window.location.hash !== shouldBeHash) {
window.location.hash = shouldBeHash;
}
}
}
/* DEFAULTS */
$jmpress('defaults').hash = {
use: true
,update: true
,bindChange: true
// NOTICE: {use: true, update: false, bindChange: true}
// will cause a error after clicking on a link to the current step
};
/* HOOKS */
$jmpress('selectInitialStep', function( step, eventData ) {
var settings = eventData.settings,
hashSettings = settings.hash,
current = eventData.current,
jmpress = $(this);
eventData.current.hashNamespace = ".jmpress-"+randomString();
// HASH CHANGE EVENT
if ( hashSettings.use ) {
if ( hashSettings.bindChange ) {
$(window).bind('hashchange'+current.hashNamespace, function(event) {
var urlItem = getElementFromUrl(settings);
if ( jmpress.jmpress('initialized') ) {
jmpress.jmpress("scrollFix");
}
if(urlItem && urlItem.length) {
if(urlItem.attr("id") !== jmpress.jmpress("active").attr("id")) {
jmpress.jmpress('select', urlItem);
}
setHash(urlItem.attr("id"));
}
event.preventDefault();
});
$(hashLink).on("click"+current.hashNamespace, function(event) {
var href = $(this).attr("href");
try {
if($(href).is(settings.stepSelector)) {
jmpress.jmpress("select", href);
event.preventDefault();
event.stopPropagation();
}
} catch(e) {}
});
}
return getElementFromUrl(settings);
}
});
$jmpress('afterDeinit', function( nil, eventData ) {
$(hashLink).off(eventData.current.hashNamespace);
$(window).unbind(eventData.current.hashNamespace);
});
$jmpress('setActive', function( step, eventData ) {
var settings = eventData.settings,
current = eventData.current;
// `#/step-id` is used instead of `#step-id` to prevent default browser
// scrolling to element in hash
if ( settings.hash.use && settings.hash.update ) {
clearTimeout(current.hashtimeout);
current.hashtimeout = setTimeout(function() {
setHash($(eventData.delegatedFrom).attr('id'));
}, settings.transitionDuration + 200);
}
});
}(jQuery, document, window));
/*
* keyboard.js
* Keyboard event mapping and default keyboard actions
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress,
jmpressNext = "next",
jmpressPrev = "prev";
/* FUNCTIONS */
function randomString() {
return "" + Math.round(Math.random() * 100000, 0);
}
function stopEvent(event) {
event.preventDefault();
event.stopPropagation();
}
/* DEFAULTS */
$jmpress('defaults').keyboard = {
use: true
,keys: {
33: jmpressPrev // pg up
,37: jmpressPrev // left
,38: jmpressPrev // up
,9: jmpressNext+":"+jmpressPrev // tab
,32: jmpressNext // space
,34: jmpressNext // pg down
,39: jmpressNext // right
,40: jmpressNext // down
,36: "home" // home
,35: "end" // end
}
,ignore: {
"INPUT": [
32 // space
,37 // left
,38 // up
,39 // right
,40 // down
]
,"TEXTAREA": [
32 // space
,37 // left
,38 // up
,39 // right
,40 // down
]
,"SELECT": [
38 // up
,40 // down
]
}
,tabSelector: "a[href]:visible, :input:visible"
};
/* HOOKS */
$jmpress('afterInit', function( nil, eventData ) {
var settings = eventData.settings,
keyboardSettings = settings.keyboard,
ignoreKeyboardSettings = keyboardSettings.ignore,
current = eventData.current,
jmpress = $(this);
// tabindex make it focusable so that it can receive key events
if(!settings.fullscreen) {
jmpress.attr("tabindex", 0);
}
current.keyboardNamespace = ".jmpress-"+randomString();
// KEYPRESS EVENT: this fixes a Opera bug
$(settings.fullscreen ? document : jmpress)
.bind("keypress"+current.keyboardNamespace, function( event ) {
for( var nodeName in ignoreKeyboardSettings ) {
if ( event.target.nodeName === nodeName && ignoreKeyboardSettings[nodeName].indexOf(event.which) !== -1 ) {
return;
}
}
if(event.which >= 37 && event.which <= 40 || event.which === 32) {
stopEvent(event);
}
});
// KEYDOWN EVENT
$(settings.fullscreen ? document : jmpress)
.bind("keydown"+current.keyboardNamespace, function( event ) {
var eventTarget = $(event.target);
if ( !settings.fullscreen && !eventTarget.closest(jmpress).length || !keyboardSettings.use ) {
return;
}
for( var nodeName in ignoreKeyboardSettings ) {
if ( eventTarget[0].nodeName === nodeName && ignoreKeyboardSettings[nodeName].indexOf(event.which) !== -1 ) {
return;
}
}
var reverseSelect = false;
var nextFocus;
if (event.which === 9) {
// tab
if ( !eventTarget.closest( jmpress.jmpress('active') ).length ) {
if ( !event.shiftKey ) {
nextFocus = jmpress.jmpress('active').find("a[href], :input").filter(":visible").first();
} else {
reverseSelect = true;
}
} else {
nextFocus = eventTarget.near( keyboardSettings.tabSelector, event.shiftKey );
if( !$(nextFocus)
.closest( settings.stepSelector )
.is(jmpress.jmpress('active') ) ) {
nextFocus = undefined;
}
}
if( nextFocus && nextFocus.length > 0 ) {
nextFocus.focus();
jmpress.jmpress("scrollFix");
stopEvent(event);
return;
} else {
if(event.shiftKey) {
reverseSelect = true;
}
}
}
var action = keyboardSettings.keys[ event.which ];
if ( typeof action === "string" ) {
if (action.indexOf(":") !== -1) {
action = action.split(":");
action = event.shiftKey ? action[1] : action[0];
}
jmpress.jmpress( action );
stopEvent(event);
} else if ( $.isFunction(action) ) {
action.call(jmpress, event);
} else if ( action ) {
jmpress.jmpress.apply( jmpress, action );
stopEvent(event);
}
if (reverseSelect) {
// tab
nextFocus = jmpress.jmpress('active').find("a[href], :input").filter(":visible").last();
nextFocus.focus();
jmpress.jmpress("scrollFix");
}
});
});
$jmpress('afterDeinit', function( nil, eventData ) {
$(document).unbind(eventData.current.keyboardNamespace);
});
}(jQuery, document, window));
/*
* viewport.js
* Scale to fit a given viewport
*/
(function( $, document, window, undefined ) {
'use strict';
function randomString() {
return "" + Math.round(Math.random() * 100000, 0);
}
var browser = (function() {
var ua = navigator.userAgent.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
return match[1] || "";
}());
var defaults = $.jmpress("defaults");
defaults.viewPort = {
width: false
,height: false
,maxScale: 0
,minScale: 0
,zoomable: 0
,zoomBindMove: true
,zoomBindWheel: true
};
var keys = defaults.keyboard.keys;
keys[browser === 'mozilla' ? 107 : 187] = "zoomIn"; // +
keys[browser === 'mozilla' ? 109 : 189] = "zoomOut"; // -
defaults.reasonableAnimation.resize = {
transitionDuration: '0s'
,transitionDelay: '0ms'
};
defaults.reasonableAnimation.zoom = {
transitionDuration: '0s'
,transitionDelay: '0ms'
};
$.jmpress("initStep", function( step, eventData ) {
for(var variable in {"viewPortHeight":1, "viewPortWidth":1, "viewPortMinScale":1, "viewPortMaxScale":1, "viewPortZoomable":1}) {
eventData.stepData[variable] = eventData.data[variable] && parseFloat(eventData.data[variable]);
}
});
$.jmpress("afterInit", function( nil, eventData ) {
var jmpress = this;
eventData.current.viewPortNamespace = ".jmpress-"+randomString();
$(window).bind("resize"+eventData.current.viewPortNamespace, function (event) {
$(jmpress).jmpress("reselect", "resize");
});
eventData.current.userZoom = 0;
eventData.current.userTranslateX = 0;
eventData.current.userTranslateY = 0;
if(eventData.settings.viewPort.zoomBindWheel) {
$(eventData.settings.fullscreen ? document : this)
.bind("mousewheel"+eventData.current.viewPortNamespace+" DOMMouseScroll"+eventData.current.viewPortNamespace, function( event, delta ) {
delta = delta || event.originalEvent.wheelDelta || -event.originalEvent.detail /* mozilla */;
var direction = (delta / Math.abs(delta));
if(direction < 0) {
$(eventData.jmpress).jmpress("zoomOut", event.originalEvent.x, event.originalEvent.y);
} else if(direction > 0) {
$(eventData.jmpress).jmpress("zoomIn", event.originalEvent.x, event.originalEvent.y);
}
return false;
});
}
if(eventData.settings.viewPort.zoomBindMove) {
$(eventData.settings.fullscreen ? document : this).bind("mousedown"+eventData.current.viewPortNamespace, function (event) {
if(eventData.current.userZoom) {
eventData.current.userTranslating = { x: event.clientX, y: event.clientY };
event.preventDefault();
event.stopImmediatePropagation();
}
}).bind("mousemove"+eventData.current.viewPortNamespace, function (event) {
var userTranslating = eventData.current.userTranslating;
if(userTranslating) {
$(jmpress).jmpress("zoomTranslate", event.clientX - userTranslating.x, event.clientY - userTranslating.y);
userTranslating.x = event.clientX;
userTranslating.y = event.clientY;
event.preventDefault();
event.stopImmediatePropagation();
}
}).bind("mouseup"+eventData.current.viewPortNamespace, function (event) {
if(eventData.current.userTranslating) {
eventData.current.userTranslating = undefined;
event.preventDefault();
event.stopImmediatePropagation();
}
});
}
});
function maxAbs(value, range) {
return Math.max(Math.min(value, range), -range);
}
function zoom(x, y, direction) {
var current = $(this).jmpress("current"),
settings = $(this).jmpress("settings"),
stepData = $(this).jmpress("active").data("stepData"),
container = $(this).jmpress("container");
if(current.userZoom === 0 && direction < 0) {
return;
}
var zoomableSteps = stepData.viewPortZoomable || settings.viewPort.zoomable;
if(current.userZoom === zoomableSteps && direction > 0) {
return;
}
current.userZoom += direction;
var halfWidth = $(container).innerWidth()/2,
halfHeight = $(container).innerHeight()/2;
x = x ? x - halfWidth : x;
y = y ? y - halfHeight : y;
// TODO this is not perfect... too much math... :(
current.userTranslateX =
maxAbs(current.userTranslateX - direction * x / current.zoomOriginWindowScale / zoomableSteps,
halfWidth * current.userZoom * current.userZoom / zoomableSteps);
current.userTranslateY =
maxAbs(current.userTranslateY - direction * y / current.zoomOriginWindowScale / zoomableSteps,
halfHeight * current.userZoom * current.userZoom / zoomableSteps);
$(this).jmpress("reselect", "zoom");
}
$.jmpress("register", "zoomIn", function(x, y) {
zoom.call(this, x||0, y||0, 1);
});
$.jmpress("register", "zoomOut", function(x, y) {
zoom.call(this, x||0, y||0, -1);
});
$.jmpress("register", "zoomTranslate", function(x, y) {
var current = $(this).jmpress("current"),
settings = $(this).jmpress("settings"),
stepData = $(this).jmpress("active").data("stepData"),
container = $(this).jmpress("container");
var zoomableSteps = stepData.viewPortZoomable || settings.viewPort.zoomable;
var halfWidth = $(container).innerWidth(),
halfHeight = $(container).innerHeight();
current.userTranslateX =
maxAbs(current.userTranslateX + x / current.zoomOriginWindowScale,
halfWidth * current.userZoom * current.userZoom / zoomableSteps);
current.userTranslateY =
maxAbs(current.userTranslateY + y / current.zoomOriginWindowScale,
halfHeight * current.userZoom * current.userZoom / zoomableSteps);
$(this).jmpress("reselect", "zoom");
});
$.jmpress('afterDeinit', function( nil, eventData ) {
$(eventData.settings.fullscreen ? document : this).unbind(eventData.current.viewPortNamespace);
$(window).unbind(eventData.current.viewPortNamespace);
});
$.jmpress("setActive", function( step, eventData ) {
var viewPort = eventData.settings.viewPort;
var viewPortHeight = eventData.stepData.viewPortHeight || viewPort.height;
var viewPortWidth = eventData.stepData.viewPortWidth || viewPort.width;
var viewPortMaxScale = eventData.stepData.viewPortMaxScale || viewPort.maxScale;
var viewPortMinScale = eventData.stepData.viewPortMinScale || viewPort.minScale;
// Correct the scale based on the window's size
var windowScaleY = viewPortHeight && $(eventData.container).innerHeight()/viewPortHeight;
var windowScaleX = viewPortWidth && $(eventData.container).innerWidth()/viewPortWidth;
var windowScale = (windowScaleX || windowScaleY) && Math.min( windowScaleX || windowScaleY, windowScaleY || windowScaleX );
if(windowScale) {
windowScale = windowScale || 1;
if(viewPortMaxScale) {
windowScale = Math.min(windowScale, viewPortMaxScale);
}
if(viewPortMinScale) {
windowScale = Math.max(windowScale, viewPortMinScale);
}
var zoomableSteps = eventData.stepData.viewPortZoomable || eventData.settings.viewPort.zoomable;
if(zoomableSteps) {
var diff = (1/windowScale) - (1/viewPortMaxScale);
diff /= zoomableSteps;
windowScale = 1/((1/windowScale) - diff * eventData.current.userZoom);
}
eventData.target.transform.reverse();
if(eventData.current.userTranslateX && eventData.current.userTranslateY) {
eventData.target.transform.push(["translate", eventData.current.userTranslateX, eventData.current.userTranslateY, 0]);
} else {
eventData.target.transform.push(["translate"]);
}
eventData.target.transform.push(["scale",
windowScale,
windowScale,
1]);
eventData.target.transform.reverse();
eventData.target.perspectiveScale /= windowScale;
}
eventData.current.zoomOriginWindowScale = windowScale;
});
$.jmpress("setInactive", function( step, eventData ) {
if(!eventData.nextStep || !step || $(eventData.nextStep).attr("id") !== $(step).attr("id")) {
eventData.current.userZoom = 0;
eventData.current.userTranslateX = 0;
eventData.current.userTranslateY = 0;
}
});
}(jQuery, document, window));
/*
* mouse.js
* Clicking to select a step
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress;
/* FUNCTIONS */
function randomString() {
return "" + Math.round(Math.random() * 100000, 0);
}
/* DEFAULTS */
$jmpress("defaults").mouse = {
clickSelects: true
};
/* HOOKS */
$jmpress("afterInit", function( nil, eventData ) {
var settings = eventData.settings,
stepSelector = settings.stepSelector,
current = eventData.current,
jmpress = $(this);
current.clickableStepsNamespace = ".jmpress-"+randomString();
jmpress.bind("click"+current.clickableStepsNamespace, function(event) {
if (!settings.mouse.clickSelects || current.userZoom) {
return;
}
// get clicked step
var clickedStep = $(event.target).closest(stepSelector);
// clicks on the active step do default
if ( clickedStep.is( jmpress.jmpress("active") ) ) {
return;
}
if (clickedStep.length) {
// select the clicked step
jmpress.jmpress("select", clickedStep[0], "click");
event.preventDefault();
event.stopPropagation();
}
});
});
$jmpress('afterDeinit', function( nil, eventData ) {
$(this).unbind(eventData.current.clickableStepsNamespace);
});
}(jQuery, document, window));
/*
* mobile.js
* Adds support for swipe on touch supported browsers
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress;
/* FUNCTIONS */
function randomString() {
return "" + Math.round(Math.random() * 100000, 0);
}
/* HOOKS */
$jmpress( 'afterInit', function( step, eventData ) {
var settings = eventData.settings,
current = eventData.current,
jmpress = eventData.jmpress;
current.mobileNamespace = ".jmpress-"+randomString();
var data, start = [0,0];
$(settings.fullscreen ? document : jmpress)
.bind("touchstart"+current.mobileNamespace, function( event ) {
data = event.originalEvent.touches[0];
start = [ data.pageX, data.pageY ];
}).bind("touchmove"+current.mobileNamespace, function( event ) {
data = event.originalEvent.touches[0];
event.preventDefault();
return false;
}).bind("touchend"+current.mobileNamespace, function( event ) {
var end = [ data.pageX, data.pageY ],
diff = [ end[0]-start[0], end[1]-start[1] ];
if(Math.max(Math.abs(diff[0]), Math.abs(diff[1])) > 50) {
diff = Math.abs(diff[0]) > Math.abs(diff[1]) ? diff[0] : diff[1];
$(jmpress).jmpress(diff > 0 ? "prev" : "next");
event.preventDefault();
return false;
}
});
});
$jmpress('afterDeinit', function( nil, eventData ) {
var settings = eventData.settings,
current = eventData.current,
jmpress = eventData.jmpress;
$(settings.fullscreen ? document : jmpress).unbind(current.mobileNamespace);
});
}(jQuery, document, window));
/*
* templates.js
* The amazing template engine
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress,
templateFromParentIdent = "_template_",
templateFromApplyIdent = "_applied_template_";
/* STATIC VARS */
var templates = {};
/* FUNCTIONS */
function addUndefined( target, values, prefix ) {
for( var name in values ) {
var targetName = name;
if ( prefix ) {
targetName = prefix + targetName.substr(0, 1).toUpperCase() + targetName.substr(1);
}
if ( $.isPlainObject(values[name]) ) {
addUndefined( target, values[name], targetName );
} else if( target[targetName] === undefined ) {
target[targetName] = values[name];
}
}
}
function applyChildrenTemplates( children, templateChildren ) {
if ($.isArray(templateChildren)) {
if (templateChildren.length < children.length) {
$.error("more nested steps than children in template");
} else {
children.each(function(idx, child) {
child = $(child);
var tmpl = child.data(templateFromParentIdent) || {};
addUndefined(tmpl, templateChildren[idx]);
child.data(templateFromParentIdent, tmpl);
});
}
} else if($.isFunction(templateChildren)) {
children.each(function(idx, child) {
child = $(child);
var tmpl = child.data(templateFromParentIdent) || {};
addUndefined(tmpl, templateChildren(idx, child, children));
child.data(templateFromParentIdent, tmpl);
});
} // TODO: else if(object)
}
function applyTemplate( data, element, template, eventData ) {
if (template.children) {
var children = element.children( eventData.settings.stepSelector );
applyChildrenTemplates( children, template.children );
}
applyTemplateData( data, template );
}
function applyTemplateData( data, template ) {
addUndefined(data, template);
}
/* HOOKS */
$jmpress("beforeInitStep", function( step, eventData ) {
step = $(step);
var data = eventData.data,
templateFromAttr = data.template,
templateFromApply = step.data(templateFromApplyIdent),
templateFromParent = step.data(templateFromParentIdent);
if(templateFromAttr) {
$.each(templateFromAttr.split(" "), function(idx, tmpl) {
var template = templates[tmpl];
applyTemplate( data, step, template, eventData );
});
}
if (templateFromApply) {
applyTemplate( data, step, templateFromApply, eventData );
}
if (templateFromParent) {
applyTemplate( data, step, templateFromParent, eventData );
step.data(templateFromParentIdent, null);
if(templateFromParent.template) {
$.each(templateFromParent.template.split(" "), function(idx, tmpl) {
var template = templates[tmpl];
applyTemplate( data, step, template, eventData );
});
}
}
});
$jmpress("beforeInit", function( nil, eventData ) {
var data = $jmpress("dataset", this),
dataTemplate = data.template,
stepSelector = eventData.settings.stepSelector;
if (dataTemplate) {
var template = templates[dataTemplate];
applyChildrenTemplates( $(this).find(stepSelector).filter(function() {
return !$(this).parent().is(stepSelector);
}), template.children );
}
});
/* EXPORTED FUNCTIONS */
$jmpress("register", "template", function( name, tmpl ) {
if (templates[name]) {
templates[name] = $.extend(true, {}, templates[name], tmpl);
} else {
templates[name] = $.extend(true, {}, tmpl);
}
});
$jmpress("register", "apply", function( selector, tmpl ) {
if( !tmpl ) {
// TODO ERROR because settings not found
var stepSelector = $(this).jmpress("settings").stepSelector;
applyChildrenTemplates( $(this).find(stepSelector).filter(function() {
return !$(this).parent().is(stepSelector);
}), selector );
} else if($.isArray(tmpl)) {
applyChildrenTemplates( $(selector), tmpl );
} else {
var template;
if(typeof tmpl === "string") {
template = templates[tmpl];
} else {
template = $.extend(true, {}, tmpl);
}
$(selector).each(function(idx, element) {
element = $(element);
var tmpl = element.data(templateFromApplyIdent) || {};
addUndefined(tmpl, template);
element.data(templateFromApplyIdent, tmpl);
});
}
});
}(jQuery, document, window));
/*
* jqevents.js
* Fires jQuery events
*/
(function( $, document, window, undefined ) {
'use strict';
/* HOOKS */
// the events should not bubble up the tree
// elsewise nested jmpress would cause buggy behavior
$.jmpress("setActive", function( step, eventData ) {
if(eventData.prevStep !== step) {
$(step).triggerHandler("enterStep");
}
});
$.jmpress("setInactive", function( step, eventData ) {
if(eventData.nextStep !== step) {
$(step).triggerHandler("leaveStep");
}
});
}(jQuery, document, window));
/*
* animation.js
* Apply custom animations to steps
*/
(function( $, document, window, undefined ) {
'use strict';
function parseSubstepInfo(str) {
var arr = str.split(" ");
var className = arr[0];
var config = { willClass: "will-"+className, doClass: "do-"+className, hasClass: "has-"+className };
var state = "";
for(var i = 1; i < arr.length; i++) {
var s = arr[i];
switch(state) {
case "":
if(s === "after") {
state = "after";
} else {
$.warn("unknown keyword in '"+str+"'. '"+s+"' unknown.");
}
break;
case "after":
if(s.match(/^[1-9][0-9]*m?s?/)) {
var value = parseFloat(s);
if(s.indexOf("ms") !== -1) {
value *= 1;
} else if(s.indexOf("s") !== -1) {
value *= 1000;
} else if(s.indexOf("m") !== -1) {
value *= 60000;
}
config.delay = value;
} else {
config.after = Array.prototype.slice.call(arr, i).join(" ");
i = arr.length;
}
}
}
return config;
}
function find(array, selector, start, end) {
end = end || (array.length - 1);
start = start || 0;
for(var i = start; i < end + 1; i++) {
if($(array[i].element).is(selector)) {
return i;
}
}
}
function addOn(list, substep, delay) {
$.each(substep._on, function(idx, child) {
list.push({substep: child.substep, delay: child.delay + delay});
addOn(list, child.substep, child.delay + delay);
});
}
$.jmpress("defaults").customAnimationDataAttribute = "jmpress";
$.jmpress("afterInit", function( nil, eventData ) {
eventData.current.animationTimeouts = [];
eventData.current.animationCleanupWaiting = [];
});
$.jmpress("applyStep", function( step, eventData ) {
// read custom animation from elements
var substepsData = {};
var listOfSubsteps = [];
$(step).find("[data-"+eventData.settings.customAnimationDataAttribute+"]")
.each(function(idx, element) {
if($(element).closest(eventData.settings.stepSelector).is(step)) {
listOfSubsteps.push({element: element});
}
});
if(listOfSubsteps.length === 0) {
return;
}
$.each(listOfSubsteps, function(idx, substep) {
substep.info = parseSubstepInfo(
$(substep.element).data(eventData.settings.customAnimationDataAttribute));
$(substep.element).addClass(substep.info.willClass);
substep._on = [];
substep._after = null;
});
var current = {_after: undefined, _on: [], info: {}}; // virtual zero step
$.each(listOfSubsteps, function(idx, substep) {
var other = substep.info.after;
if(other) {
if(other === "step") {
other = current;
} else if(other === "prev") {
other = listOfSubsteps[idx-1];
} else {
var index = find(listOfSubsteps, other, 0, idx - 1);
if(index === undefined) {
index = find(listOfSubsteps, other);
}
other = (index === undefined || index === idx) ? listOfSubsteps[idx-1] : listOfSubsteps[index];
}
} else {
other = listOfSubsteps[idx-1];
}
if(other) {
if(!substep.info.delay) {
if(!other._after) {
other._after = substep;
return;
}
other = other._after;
}
other._on.push({substep: substep, delay: substep.info.delay || 0});
}
});
if(current._after === undefined && current._on.length === 0) {
var startStep = find(listOfSubsteps, eventData.stepData.startSubstep) || 0;
current._after = listOfSubsteps[startStep];
}
var substepsInOrder = [];
function findNextFunc(idx, item) {
if(item.substep._after) {
current = item.substep._after;
return false;
}
}
do {
var substepList = [{substep: current, delay: 0}];
addOn(substepList, current, 0);
substepsInOrder.push(substepList);
current = null;
$.each(substepList, findNextFunc);
} while(current);
substepsData.list = substepsInOrder;
$(step).data("substepsData", substepsData);
});
$.jmpress("unapplyStep", function( step, eventData ) {
var substepsData = $(step).data("substepsData");
if(substepsData) {
$.each(substepsData.list, function(idx, activeSubsteps) {
$.each(activeSubsteps, function(idx, substep) {
if(substep.substep.info.willClass) {
$(substep.substep.element).removeClass(substep.substep.info.willClass);
}
if(substep.substep.info.hasClass) {
$(substep.substep.element).removeClass(substep.substep.info.hasClass);
}
if(substep.substep.info.doClass) {
$(substep.substep.element).removeClass(substep.substep.info.doClass);
}
});
});
}
});
$.jmpress("setActive", function(step, eventData) {
var substepsData = $(step).data("substepsData");
if(!substepsData) {
return;
}
if(eventData.substep === undefined) {
eventData.substep =
(eventData.reason === "prev" ?
substepsData.list.length-1 :
0
);
}
var substep = eventData.substep;
$.each(eventData.current.animationTimeouts, function(idx, timeout) {
clearTimeout(timeout);
});
eventData.current.animationTimeouts = [];
$.each(substepsData.list, function(idx, activeSubsteps) {
var applyHas = idx < substep;
var applyDo = idx <= substep;
$.each(activeSubsteps, function(idx, substep) {
if(substep.substep.info.hasClass) {
$(substep.substep.element)[(applyHas?"add":"remove")+"Class"](substep.substep.info.hasClass);
}
function applyIt() {
$(substep.substep.element).addClass(substep.substep.info.doClass);
}
if(applyDo && !applyHas && substep.delay && eventData.reason !== "prev") {
if(substep.substep.info.doClass) {
$(substep.substep.element).removeClass(substep.substep.info.doClass);
eventData.current.animationTimeouts.push(setTimeout(applyIt, substep.delay));
}
} else {
if(substep.substep.info.doClass) {
$(substep.substep.element)[(applyDo?"add":"remove")+"Class"](substep.substep.info.doClass);
}
}
});
});
});
$.jmpress("setInactive", function(step, eventData) {
if(eventData.nextStep === step) {
return;
}
function cleanupAnimation( substepsData ) {
$.each(substepsData.list, function(idx, activeSubsteps) {
$.each(activeSubsteps, function(idx, substep) {
if(substep.substep.info.hasClass) {
$(substep.substep.element).removeClass(substep.substep.info.hasClass);
}
if(substep.substep.info.doClass) {
$(substep.substep.element).removeClass(substep.substep.info.doClass);
}
});
});
}
$.each(eventData.current.animationCleanupWaiting, function(idx, item) {
cleanupAnimation(item);
});
eventData.current.animationCleanupWaiting = [];
var substepsData = $(step).data("substepsData");
if(substepsData) {
eventData.current.animationCleanupWaiting.push( substepsData );
}
});
$.jmpress("selectNext", function( step, eventData ) {
if(eventData.substep === undefined) {
return;
}
var substepsData = $(step).data("substepsData");
if(!substepsData) {
return;
}
if(eventData.substep < substepsData.list.length-1) {
return {step: step, substep: eventData.substep+1};
}
});
$.jmpress("selectPrev", function( step, eventData ) {
if(eventData.substep === undefined) {
return;
}
var substepsData = $(step).data("substepsData");
if(!substepsData) {
return;
}
if(eventData.substep > 0) {
return {step: step, substep: eventData.substep-1};
}
});
}(jQuery, document, window));
/*!
* plugin for jmpress.js v0.4.5
*
* Copyright 2013 Kyle Robinson Young @shama & Tobias Koppers @sokra
* Licensed MIT
* http://www.opensource.org/licenses/mit-license.php
*//*
* jmpress.toggle plugin
* For binding a key to toggle de/initialization of jmpress.js.
*/
(function( $, document, window, undefined ) {
'use strict';
$.jmpress("register", "toggle", function( key, config, initial ) {
var jmpress = this;
$(document).bind("keydown", function( event ) {
if ( event.keyCode === key ) {
if ($(jmpress).jmpress("initialized")) {
$(jmpress).jmpress("deinit");
} else {
$(jmpress).jmpress(config);
}
}
});
if ( initial ) {
$(jmpress).jmpress(config);
}
});
}(jQuery, document, window));
/*
* jmpress.secondary plugin
* Apply a secondary animation when step is selected.
*/
(function( $, document, window, undefined ) {
'use strict';
$.jmpress("initStep", function( step, eventData ) {
for(var name in eventData.data) {
if(name.indexOf("secondary") === 0) {
eventData.stepData[name] = eventData.data[name];
}
}
});
function exchangeIf(childStepData, condition, step) {
if(childStepData.secondary &&
childStepData.secondary.split(" ").indexOf(condition) !== -1) {
for(var name in childStepData) {
if(name.length > 9 && name.indexOf("secondary") === 0) {
var tmp = childStepData[name];
var normal = name.substr(9);
normal = normal.substr(0, 1).toLowerCase() + normal.substr(1);
childStepData[name] = childStepData[normal];
childStepData[normal] = tmp;
}
}
$(this).jmpress("reapply", $(step));
}
}
$.jmpress("beforeActive", function( step, eventData ) {
exchangeIf.call(eventData.jmpress, $(step).data("stepData"), "self", step);
var parent = $(step).parent();
$(parent)
.children(eventData.settings.stepSelector)
.each(function(idx, child) {
var childStepData = $(child).data("stepData");
exchangeIf.call(eventData.jmpress, childStepData, "siblings", child);
});
function grandchildrenFunc(idx, child) {
var childStepData = $(child).data("stepData");
exchangeIf.call(eventData.jmpress, childStepData, "grandchildren", child);
}
for(var i = 1; i < eventData.parents.length; i++) {
$(eventData.parents[i])
.children(eventData.settings.stepSelector)
.each();
}
});
$.jmpress("setInactive", function( step, eventData ) {
exchangeIf.call(eventData.jmpress, $(step).data("stepData"), "self", step);
var parent = $(step).parent();
$(parent)
.children(eventData.settings.stepSelector)
.each(function(idx, child) {
var childStepData = $(child).data("stepData");
exchangeIf.call(eventData.jmpress, childStepData, "siblings", child);
});
function grandchildrenFunc(idx, child) {
var childStepData = $(child).data("stepData");
exchangeIf.call(eventData.jmpress, childStepData, "grandchildren", child);
}
for(var i = 1; i < eventData.parents.length; i++) {
$(eventData.parents[i])
.children(eventData.settings.stepSelector)
.each(grandchildrenFunc);
}
});
}(jQuery, document, window));
/*
* jmpress.duration plugin
* For auto advancing steps after a given duration and optionally displaying a
* progress bar.
*/
(function( $, document, window, undefined ) {
'use strict';
$.jmpress("defaults").duration = {
defaultValue: -1
,defaultAction: "next"
,barSelector: undefined
,barProperty: "width"
,barPropertyStart: "0"
,barPropertyEnd: "100%"
};
$.jmpress("initStep", function( step, eventData ) {
eventData.stepData.duration = eventData.data.duration && parseInt(eventData.data.duration, 10);
eventData.stepData.durationAction = eventData.data.durationAction;
});
$.jmpress("setInactive", function( step, eventData ) {
var settings = eventData.settings,
durationSettings = settings.duration,
current = eventData.current;
var dur = eventData.stepData.duration || durationSettings.defaultValue;
if( current.durationTimeout ) {
if( durationSettings.barSelector ) {
var css = {
transitionProperty: durationSettings.barProperty
,transitionDuration: '0'
,transitionDelay: '0'
,transitionTimingFunction: 'linear'
};
css[durationSettings.barProperty] = durationSettings.barPropertyStart;
var bars = $(durationSettings.barSelector);
$.jmpress("css", bars, css);
bars.each(function(idx, element) {
var next = $(element).next();
var parent = $(element).parent();
$(element).detach();
if(next.length) {
next.insertBefore(element);
} else {
parent.append(element);
}
});
}
clearTimeout(current.durationTimeout);
delete current.durationTimeout;
}
});
$.jmpress("setActive", function( step, eventData ) {
var settings = eventData.settings,
durationSettings = settings.duration,
current = eventData.current;
var dur = eventData.stepData.duration || durationSettings.defaultValue;
if( dur && dur > 0 ) {
if( durationSettings.barSelector ) {
var css = {
transitionProperty: durationSettings.barProperty
,transitionDuration: (dur-settings.transitionDuration*2/3-100)+"ms"
,transitionDelay: (settings.transitionDuration*2/3)+'ms'
,transitionTimingFunction: 'linear'
};
css[durationSettings.barProperty] = durationSettings.barPropertyEnd;
$.jmpress("css", $(durationSettings.barSelector), css);
}
var jmpress = this;
if(current.durationTimeout) {
clearTimeout(current.durationTimeout);
current.durationTimeout = undefined;
}
current.durationTimeout = setTimeout(function() {
var action = eventData.stepData.durationAction || durationSettings.defaultAction;
$(jmpress).jmpress(action);
}, dur);
}
});
}(jQuery, document, window));
/*
* jmpress.presentation-mode plugin
* Display a window for the presenter with notes and a control and view of the
* presentation
*/
(function( $, document, window, undefined ) {
'use strict';
var $jmpress = $.jmpress;
var PREFIX = "jmpress-presentation-";
/* FUNCTIONS */
function randomString() {
return "" + Math.round(Math.random() * 100000, 0);
}
/* DEFAULTS */
$jmpress("defaults").presentationMode = {
use: true,
url: "presentation-screen.html",
notesUrl: false,
transferredValues: ["userZoom", "userTranslateX", "userTranslateY"]
};
$jmpress("defaults").keyboard.keys[80] = "presentationPopup"; // p key
/* HOOKS */
$jmpress("afterInit", function( nil, eventData) {
var current = eventData.current;
current.selectMessageListeners = [];
if(eventData.settings.presentationMode.use) {
window.addEventListener("message", function(event) {
// We do not test orgin, because we want to accept messages
// from all orgins
try {
if(typeof event.data !== "string" || event.data.indexOf(PREFIX) !== 0) {
return;
}
var json = JSON.parse(event.data.slice(PREFIX.length));
switch(json.type) {
case "select":
$.each(eventData.settings.presentationMode.transferredValues, function(idx, name) {
eventData.current[name] = json[name];
});
if(/[a-z0-9\-]+/i.test(json.targetId) && typeof json.substep in {number:1,undefined:1}) {
$(eventData.jmpress).jmpress("select", {step: "#"+json.targetId, substep: json.substep}, json.reason);
} else {
$.error("For security reasons the targetId must match /[a-z0-9\\-]+/i and substep must be a number.");
}
break;
case "listen":
current.selectMessageListeners.push(event.source);
break;
case "ok":
clearTimeout(current.presentationPopupTimeout);
break;
case "read":
try {
event.source.postMessage(PREFIX + JSON.stringify({type: "url", url: window.location.href, notesUrl: eventData.settings.presentationMode.notesUrl}), "*");
} catch(e) {
$.error("Cannot post message to source: " + e);
}
break;
default:
throw "Unknown message type: " + json.type;
}
} catch(e) {
$.error("Received message is malformed: " + e);
}
});
try {
if(window.parent && window.parent !== window) {
window.parent.postMessage(PREFIX + JSON.stringify({
"type": "afterInit"
}), "*");
}
} catch(e) {
$.error("Cannot post message to parent: " + e);
}
}
});
$jmpress("afterDeinit", function( nil, eventData) {
if(eventData.settings.presentationMode.use) {
try {
if(window.parent && window.parent !== window) {
window.parent.postMessage(PREFIX + JSON.stringify({
"type": "afterDeinit"
}), "*");
}
} catch(e) {
$.error("Cannot post message to parent: " + e);
}
}
});
$jmpress("setActive", function( step, eventData) {
var stepId = $(eventData.delegatedFrom).attr("id"),
substep = eventData.substep,
reason = eventData.reason;
$.each(eventData.current.selectMessageListeners, function(idx, listener) {
try {
var msg = {
"type": "select",
"targetId": stepId,
"substep": substep,
"reason": reason
};
$.each(eventData.settings.presentationMode.transferredValues, function(idx, name) {
msg[name] = eventData.current[name];
});
listener.postMessage(PREFIX + JSON.stringify(msg), "*");
} catch(e) {
$.error("Cannot post message to listener: " + e);
}
});
});
$jmpress("register", "presentationPopup", function() {
function trySend() {
jmpress.jmpress("current").presentationPopupTimeout = setTimeout(trySend, 100);
try {
popup.postMessage(PREFIX + JSON.stringify({type: "url", url: window.location.href, notesUrl: jmpress.jmpress("settings").presentationMode.notesUrl}), "*");
} catch(e) {
}
}
var jmpress = $(this),
popup;
if(jmpress.jmpress("settings").presentationMode.use) {
popup = window.open($(this).jmpress("settings").presentationMode.url);
jmpress.jmpress("current").presentationPopupTimeout = setTimeout(trySend, 100);
}
});
}(jQuery, document, window));