aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartek Szopka <bartek.szopka+github@gmail.com>2012-03-12 21:51:07 +0000
committerBartek Szopka <bartek.szopka+github@gmail.com>2012-03-12 21:51:07 +0000
commit70bc3b737b4db64c648873620b14ba77004150ba (patch)
treedeb337a06ec971c9cabb234ff61a01c48cd6b0bc
parent8220ab9393a9b135b6171d700e7c5f9167379420 (diff)
downloadimpress.js-70bc3b737b4db64c648873620b14ba77004150ba.tar.gz
"impressive API update - added initialization `init` function and event"
-rw-r--r--index.html5
-rw-r--r--js/impress.js296
2 files changed, 160 insertions, 141 deletions
diff --git a/index.html b/index.html
index b77fe6f..0a885a8 100644
--- a/index.html
+++ b/index.html
@@ -318,14 +318,14 @@ if ("ontouchstart" in document.documentElement) {
In here I just include full source of the script to make it more readable.
- You also need to call a `impress()` function to initialize impress.js presentation.
+ You also need to call a `impress().init()` function to initialize impress.js presentation.
And you should do it in the end of your document. Not only because it's a good practice, but also
because it should be done when the whole document is ready.
Of course you can wrap it in any kind of "DOM ready" event, but I was too lazy to do so ;)
-->
<script src="js/impress.js"></script>
-<script>impress();</script>
+<script>impress().init();</script>
<!--
@@ -337,6 +337,7 @@ if ("ontouchstart" in document.documentElement) {
and you will get three functions you can call:
+ `api.init()` - initializes the presentation,
`api.next()` - moves to next step of the presentation,
`api.prev()` - moves to previous step of the presentation
`api.stepTo( stepElement ) - moves the presentation to given step element (the DOM element of the step).
diff --git a/js/impress.js b/js/impress.js
index 2e3b928..ac692d9 100644
--- a/js/impress.js
+++ b/js/impress.js
@@ -181,83 +181,67 @@
return roots["impress-root-" + rootId];
}
- // DOM ELEMENTS
+ var stepData = {};
- var root = byId( rootId );
+ var isStep = function ( el ) {
+ return !!(el && el.id && stepData["impress-" + el.id]);
+ };
- // viewport updates for iPad
- var meta = $("meta[name='viewport']") || document.createElement("meta");
- // hardcoding these values looks pretty bad, as they kind of depend on the content
- // so they should be at least configurable
- meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no";
- if (meta.parentNode !== document.head) {
- meta.name = 'viewport';
- document.head.appendChild(meta);
- }
+ var active = null;
- // initialize configuration object
- var rootData = root.dataset;
- var config = {
- width: toNumber(rootData.width, defaults.width),
- height: toNumber(rootData.height, defaults.height),
- maxScale: toNumber(rootData.maxScale, defaults.maxScale),
- minScale: toNumber(rootData.minScale, defaults.minScale),
-
- perspective: toNumber(rootData.perspective, defaults.perspective),
-
- transitionDuration: toNumber(rootData.transitionDuration, defaults.transitionDuration)
+ // step events
+
+ var triggerEvent = function (el, eventName) {
+ var event = document.createEvent("CustomEvent");
+ event.initCustomEvent(eventName, true, true, {});
+ el.dispatchEvent(event);
};
- var canvas = document.createElement("div");
- canvas.className = "canvas";
+ var lastEntered = null;
+ var onStepEnter = function (step) {
+ if (lastEntered !== step) {
+ triggerEvent(step, "impressStepEnter");
+ lastEntered = step;
+ }
+ };
- arrayify( root.childNodes ).forEach(function ( el ) {
- canvas.appendChild( el );
- });
- root.appendChild(canvas);
+ var onStepLeave = function (step) {
+ if (lastEntered === step) {
+ triggerEvent(step, "impressStepLeave");
+ }
+ };
- var steps = $$(".step", root);
+ // transitionEnd event handler
+
+ var expectedTransitionTarget = null;
- var windowScale = computeWindowScale( config );
+ var onTransitionEnd = function (event) {
+ // we only care about transitions on `root` and `canvas` elements
+ if (event.target === expectedTransitionTarget) {
+ onStepEnter(active);
+ event.stopPropagation(); // prevent propagation from `canvas` to `root`
+ }
+ };
- // SETUP
- // set initial values and defaults
+ // current state (position, rotation and scale) of the presentation
+ var currentState = null;
- document.documentElement.style.height = "100%";
+ // array of step elements
+ var steps = null;
- css(body, {
- height: "100%",
- overflow: "hidden"
- });
-
- var props = {
- position: "absolute",
- transformOrigin: "top left",
- transition: "all 0s ease-in-out",
- transformStyle: "preserve-3d"
- };
+ // configuration options
+ var config = null;
- css(root, props);
- css(root, {
- top: "50%",
- left: "50%",
- transform: perspective( config.perspective/windowScale ) + scale( windowScale )
- });
- css(canvas, props);
+ // scale factor of the browser window
+ var windowScale = null;
- var current = {
- translate: { x: 0, y: 0, z: 0 },
- rotate: { x: 0, y: 0, z: 0 },
- scale: 1
- };
-
- var stepData = {};
+ // root presentation elements
+ var root = byId( rootId );
+ var canvas = document.createElement("div");
- var isStep = function ( el ) {
- return !!(el && el.id && stepData["impress-" + el.id]);
- };
+ var initialized = false;
- steps.forEach(function ( el, idx ) {
+ var initStep = function ( el, idx ) {
var data = el.dataset,
step = {
translate: {
@@ -288,49 +272,81 @@
scale(step.scale),
transformStyle: "preserve-3d"
});
-
- });
-
- var active = null;
-
- // step events
-
- var triggerEvent = function (el, eventName) {
- var event = document.createEvent("CustomEvent");
- event.initCustomEvent(eventName, true, true);
- el.dispatchEvent(event);
- };
-
- var lastEntered = null;
- var onStepEnter = function (step) {
- if (lastEntered !== step) {
- triggerEvent(step, "impressStepEnter");
- lastEntered = step;
- }
- };
-
- var onStepLeave = function (step) {
- if (lastEntered === step) {
- triggerEvent(step, "impressStepLeave");
- }
};
- // transitionEnd event handler
-
- var expectedTransitionTarget = null;
-
- var onTransitionEnd = function (event) {
- // we only care about transitions on `root` and `canvas` elements
- if (event.target === expectedTransitionTarget) {
- onStepEnter(active);
- event.stopPropagation(); // prevent propagation from `canvas` to `root`
+ var init = function () {
+ if (initialized) { return; }
+
+ // setup viewport for mobile devices
+ var meta = $("meta[name='viewport']") || document.createElement("meta");
+ meta.content = "width=device-width, minimum-scale=1, maximum-scale=1, user-scalable=no";
+ if (meta.parentNode !== document.head) {
+ meta.name = 'viewport';
+ document.head.appendChild(meta);
}
+
+ // initialize configuration object
+ var rootData = root.dataset;
+ config = {
+ width: toNumber( rootData.width, defaults.width ),
+ height: toNumber( rootData.height, defaults.height ),
+ maxScale: toNumber( rootData.maxScale, defaults.maxScale ),
+ minScale: toNumber( rootData.minScale, defaults.minScale ),
+ perspective: toNumber( rootData.perspective, defaults.perspective ),
+ transitionDuration: toNumber( rootData.transitionDuration, defaults.transitionDuration )
+ };
+
+ windowScale = computeWindowScale( config );
+
+ // wrap steps with "canvas" element
+ arrayify( root.childNodes ).forEach(function ( el ) {
+ canvas.appendChild( el );
+ });
+ root.appendChild(canvas);
+
+ // set initial styles
+ document.documentElement.style.height = "100%";
+
+ css(body, {
+ height: "100%",
+ overflow: "hidden"
+ });
+
+ var rootStyles = {
+ position: "absolute",
+ transformOrigin: "top left",
+ transition: "all 0s ease-in-out",
+ transformStyle: "preserve-3d"
+ };
+
+ css(root, rootStyles);
+ css(root, {
+ top: "50%",
+ left: "50%",
+ transform: perspective( config.perspective/windowScale ) + scale( windowScale )
+ });
+ css(canvas, rootStyles);
+
+ root.addEventListener(transitionEnd, onTransitionEnd, false);
+ canvas.addEventListener(transitionEnd, onTransitionEnd, false);
+
+ // get and init steps
+ steps = $$(".step", root);
+ steps.forEach( initStep );
+
+ currentState = {
+ translate: { x: 0, y: 0, z: 0 },
+ rotate: { x: 0, y: 0, z: 0 },
+ scale: 1
+ };
+
+ initialized = true;
+
+ triggerEvent(root, "impressInit");
};
- root.addEventListener(transitionEnd, onTransitionEnd, false);
- canvas.addEventListener(transitionEnd, onTransitionEnd, false);
var stepTo = function ( el, force ) {
- if ( !isStep(el) || (el === active && !force) ) {
+ if ( !initialized || !isStep(el) || (el === active && !force) ) {
// selected element is not defined as step or is already active
return false;
}
@@ -370,7 +386,7 @@
};
// check if the transition is zooming in or not
- var zoomin = target.scale >= current.scale;
+ var zoomin = target.scale >= currentState.scale;
// if presentation starts (nothing is active yet)
// don't animate (set duration to 0)
@@ -378,12 +394,12 @@
delay = (config.transitionDuration / 2);
if (force) {
- windowScale = computeWindowScale();
+ windowScale = computeWindowScale(config);
}
var targetScale = target.scale * windowScale;
- expectedTransitionTarget = target.scale > current.scale ? root : canvas;
+ expectedTransitionTarget = target.scale > currentState.scale ? root : canvas;
if (active) {
onStepLeave(active);
@@ -403,7 +419,7 @@
transitionDelay: (zoomin ? 0 : delay) + "ms"
});
- current = target;
+ currentState = target;
active = el;
if (duration === 0) {
@@ -427,47 +443,49 @@
return stepTo(next);
};
- // STEP CLASSES
- steps.forEach(function (step) {
- step.classList.add("future");
- });
-
- root.addEventListener("impressStepEnter", function (event) {
- event.target.classList.remove("past");
- event.target.classList.remove("future");
- event.target.classList.add("present");
- }, false);
-
- root.addEventListener("impressStepLeave", function (event) {
- event.target.classList.remove("present");
- event.target.classList.add("past");
- }, false);
-
- // HASH CHANGE
-
- // `#/step-id` is used instead of `#step-id` to prevent default browser
- // scrolling to element in hash
- //
- // and it has to be set after animation finishes, because in Chrome it
- // causes transtion being laggy
- // BUG: http://code.google.com/p/chromium/issues/detail?id=62820
- root.addEventListener("impressStepEnter", function (event) {
- window.location.hash = "#/" + event.target.id;
- }, false);
-
- window.addEventListener("hashchange", function () {
- stepTo( getElementFromUrl() );
+ root.addEventListener("impressInit", function(){
+ // STEP CLASSES
+ steps.forEach(function (step) {
+ step.classList.add("future");
+ });
+
+ root.addEventListener("impressStepEnter", function (event) {
+ event.target.classList.remove("past");
+ event.target.classList.remove("future");
+ event.target.classList.add("present");
+ }, false);
+
+ root.addEventListener("impressStepLeave", function (event) {
+ event.target.classList.remove("present");
+ event.target.classList.add("past");
+ }, false);
+
}, false);
- window.addEventListener("orientationchange", function () {
- window.scrollTo(0, 0);
+ root.addEventListener("impressInit", function(){
+ // HASH CHANGE
+
+ // `#/step-id` is used instead of `#step-id` to prevent default browser
+ // scrolling to element in hash
+ //
+ // and it has to be set after animation finishes, because in Chrome it
+ // causes transtion being laggy
+ // BUG: http://code.google.com/p/chromium/issues/detail?id=62820
+ root.addEventListener("impressStepEnter", function (event) {
+ window.location.hash = "#/" + event.target.id;
+ }, false);
+
+ window.addEventListener("hashchange", function () {
+ stepTo( getElementFromUrl() );
+ }, false);
+
+ // START
+ // by selecting step defined in url or first step of the presentation
+ stepTo(getElementFromUrl() || steps[0]);
}, false);
- // START
- // by selecting step defined in url or first step of the presentation
- stepTo(getElementFromUrl() || steps[0]);
-
return (roots[ "impress-root-" + rootId ] = {
+ init: init,
stepTo: stepTo,
next: next,
prev: prev