From a83ef869d5159ab5c190524fbfa1a30880a26025 Mon Sep 17 00:00:00 2001 From: Kim Wittenburg Date: Tue, 31 Oct 2017 14:39:33 +0100 Subject: [PATCH] Archive Project --- .babelrc | 3 + .gitignore | 11 + Play Button.pxm | Bin 0 -> 255735 bytes README.md | 3 + TuneKit/sounds/Exit.aif | Bin 0 -> 26104 bytes TuneKit/sounds/Limit.aif | Bin 0 -> 60816 bytes TuneKit/sounds/Selection.aif | Bin 0 -> 13518 bytes TuneKit/sounds/SelectionChange.aif | Bin 0 -> 22292 bytes TuneKit/src/TuneKit.js | 5941 +++++++++++++++++++++ compile.sh | 67 + data.json | 76 + package-lock.json | 3246 +++++++++++ package.json | 10 + src/controllers/chapters.js | 74 + src/controllers/data.js.mustache | 25 + src/controllers/features.js | 87 + src/controllers/home.js | 32 + src/controllers/navigation.js | 31 + src/controllers/strings.js | 37 + src/css/_functions.scss | 23 + src/css/_variables.scss | 124 + src/css/carousel.scss | 92 + src/css/home.scss | 26 + src/css/list-on-right.scss | 95 + src/css/shared.scss | 103 + src/iTunesMetadata.plist.mustache | 58 + src/images/interface/buttonPlayCircle.png | Bin 0 -> 73672 bytes src/index.html | 33 + src/manifest.xml.mustache | 14 + 29 files changed, 10211 insertions(+) create mode 100644 .babelrc create mode 100644 .gitignore create mode 100644 Play Button.pxm create mode 100644 README.md create mode 100644 TuneKit/sounds/Exit.aif create mode 100644 TuneKit/sounds/Limit.aif create mode 100644 TuneKit/sounds/Selection.aif create mode 100644 TuneKit/sounds/SelectionChange.aif create mode 100644 TuneKit/src/TuneKit.js create mode 100644 compile.sh create mode 100644 data.json create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/controllers/chapters.js create mode 100644 src/controllers/data.js.mustache create mode 100644 src/controllers/features.js create mode 100644 src/controllers/home.js create mode 100644 src/controllers/navigation.js create mode 100644 src/controllers/strings.js create mode 100644 src/css/_functions.scss create mode 100644 src/css/_variables.scss create mode 100644 src/css/carousel.scss create mode 100644 src/css/home.scss create mode 100644 src/css/list-on-right.scss create mode 100644 src/css/shared.scss create mode 100644 src/iTunesMetadata.plist.mustache create mode 100644 src/images/interface/buttonPlayCircle.png create mode 100644 src/index.html create mode 100644 src/manifest.xml.mustache diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..2f01e1d --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["env"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c628afc --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +# IDEA Project Files +.idea + +# Node.js +node_modules/ + +# Media Assets +assets/ + +# Generated Files +*.ite \ No newline at end of file diff --git a/Play Button.pxm b/Play Button.pxm new file mode 100644 index 0000000000000000000000000000000000000000..562019b9ed7fb0fdeded8bce0126aee74331eff1 GIT binary patch literal 255735 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�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 W^K%tiI_hNVcds3K=AWZ}PyYut9gt}N literal 0 HcmV?d00001 diff --git a/README.md b/README.md new file mode 100644 index 0000000..8676477 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# iTunes Extras Template + +## Asset File Structure and Naming \ No newline at end of file diff --git a/TuneKit/sounds/Exit.aif b/TuneKit/sounds/Exit.aif new file mode 100644 index 0000000000000000000000000000000000000000..c2d59461caf7802cc629e1642d2d3424a1b3c372 GIT binary patch literal 26104 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 H>0SQ=&Duy; literal 0 HcmV?d00001 diff --git a/TuneKit/sounds/Limit.aif b/TuneKit/sounds/Limit.aif new file mode 100644 index 0000000000000000000000000000000000000000..e7d5aa6ea951f17c59df46379ca31a343b2afccc GIT binary patch literal 60816 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 literal 0 HcmV?d00001 diff --git a/TuneKit/sounds/Selection.aif b/TuneKit/sounds/Selection.aif new file mode 100644 index 0000000000000000000000000000000000000000..fa970f34dcef8ae970d3371cd06626764b364c2d GIT binary patch literal 13518 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 literal 0 HcmV?d00001 diff --git a/TuneKit/src/TuneKit.js b/TuneKit/src/TuneKit.js new file mode 100644 index 0000000..2feba6e --- /dev/null +++ b/TuneKit/src/TuneKit.js @@ -0,0 +1,5941 @@ +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +const TK_VERSION = '2009-11-19'; + +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/** + * The keyboard identifier for the backspace key. + * @constant + * @type int + */ +const KEYBOARD_BACKSPACE = 8; +/** + * The keyboard identifier for the left key. + * @constant + * @type int + */ +const KEYBOARD_LEFT = 37; +/** + * The keyboard identifier for the right key. + * @constant + * @type int + */ +const KEYBOARD_RIGHT = 39; +/** + * The keyboard identifier for the up key. + * @constant + * @type int + */ +const KEYBOARD_UP = 38; +/** + * The keyboard identifier for the down key. + * @constant + * @type int + */ +const KEYBOARD_DOWN = 40; +/** + * The keyboard identifier for the return key. + * @constant + * @type int + */ +const KEYBOARD_RETURN = 13; + +/** + * Indicates whether TuneKit is running on Apple TV. + * @constant + * @type bool + */ +const IS_APPLE_TV = (window.iTunes !== undefined && window.iTunes.platform == 'AppleTV'); +/** + * The Apple TV-specific iTunes system sounds interface. + * @constant + * @type bool + * @private + */ +const ATV_SOUNDS = IS_APPLE_TV ? window.iTunes.getSystemSounds() : null; + +/** + * The move sound of the Apple TV user interface. + * @constant + * @type Object + */ +const SOUND_MOVED = IS_APPLE_TV ? ATV_SOUNDS.SystemSoundScrollStart : new Audio('TuneKit/sounds/SelectionChange.aif'); +/** + * The selection sound of the Apple TV user interface. + * @constant + * @type Object + */ +const SOUND_ACTIVATED = IS_APPLE_TV ? ATV_SOUNDS.SystemSoundSelect : new Audio('TuneKit/sounds/Selection.aif'); +/** + * The limit sound of the Apple TV user interface. + * @constant + * @type Object + */ +const SOUND_LIMIT = IS_APPLE_TV ? ATV_SOUNDS.SystemSoundScrollLimit : new Audio('TuneKit/sounds/Limit.aif'); +/** + * The exit sound of the Apple TV user interface. + * @constant + * @type Object + */ +const SOUND_EXIT = IS_APPLE_TV ? ATV_SOUNDS.SystemSoundExit : new Audio('TuneKit/sounds/Exit.aif'); + +/** + * @class + * @name TKUtils + * + * @since TuneKit 1.0 + */ +function TKUtils () { +}; + +/* ==================== SOUNDS ==================== */ + +/** + * Plays a sound. + * + * @param {Object} sound The sound to play, which is either an audio element or an iTunes system sound identifier on Apple TV. + */ +TKUtils.playSound = function (sound) { + if (IS_APPLE_TV) { + ATV_SOUNDS.playSystemSound(sound); + } + else { + sound.play(); + } +}; + +/* ==================== TRANSFORMS SHORTHANDS ==================== */ + +/** + * Prints a translate3d() command that can be used as input for a -webkit-transform property. + * + * @param {int} tx The x coordinate for the translation. + * @param {int} ty The y coordinate for the translation + * + * @returns {String} The translate3d() command + */ +TKUtils.t = function (tx, ty) { + return 'translate3d(' + tx + 'px, ' + ty + 'px, 0)'; +}; + +/** + * Creates a CSS string representation for a number in pixels. + * + * @param {number} value The value to be converted. + * + * @returns {String} A CSS string representation for value in pixels. + */ +TKUtils.px = function (value) { + return value + 'px'; +}; + +/* ==================== Array ==================== */ + +/** + * Copies all properties from one object onto another. + * + * @param {Object} sourceObject The object from which we will copy properties. + * @param {Object} targetObject The array onto which we will copy properties. + */ +TKUtils.copyPropertiesFromSourceToTarget = function (source, target) { + for (var property in source) { + target[property] = source[property]; + } +}; + +/* ==================== Delegates ==================== */ + +/** + * Indicates whether an object is a Function. + * + * @param {Object} object The object purported to be a Function. + * + * @returns {bool} Whether the object is a Function. + */ +TKUtils.objectIsFunction = function (object) { + return (typeof object == 'function'); +}; + +/** + * Indicates whether an object is undefined. + * + * @param {Object} object The object purported to be undefined. + * + * @returns {bool} Whether the object is undefined. + */ +TKUtils.objectIsUndefined = function (object) { + return (object === undefined); +}; + +/** + * Indicates whether an object is a string literal or a String instance. + * + * @param {Object} object The object purported to be a string literal or a String instance. + * + * @returns {bool} Whether the object is a string literal or a String instance. + */ +TKUtils.objectIsString = function (object) { + return (typeof object == 'string' || object instanceof String); +}; + +/** + * Indicates whether an object is an Array. + * + * @param {Object} object The object purported to be an Array. + * + * @returns {bool} Whether the object is an Array. + */ +TKUtils.objectIsArray = function (object) { + return (object instanceof Array); +}; + +/** + * Indicates whether an object implements a given method, useful to check if a delegate + * object implements a given delegate method. + * + * @param {Object} object The object purported to implement a given method. + * @param {String} methodNameAsString The method name as a String. + * + * @returns {bool} Whether the object implements the given method. + */ +TKUtils.objectHasMethod = function (object, methodNameAsString) { + return ( object !== null && + !this.objectIsUndefined(object) && + !this.objectIsUndefined(object[methodNameAsString]) && + this.objectIsFunction(object[methodNameAsString]) + ); +}; + +/* ==================== INIT ==================== */ + +/** + * Sets up the .displayNames for all functions defined on the specified class, including its prototype. + * + * @param {Object} class The class. + * @param {String} className The class name as a string, in case it can not be derived from class. Optional. + */ +TKUtils.setupDisplayNames = function (object, className) { + var class_name = className || object.name; + for (var i in object) { + // make sure we don't touch properties that were synthetized + if (object.__lookupGetter__(i)) { + continue; + } + var prop = object[i]; + if (TKUtils.objectIsFunction(prop)) { + prop.displayName = TKUtils.createDisplayName(class_name, i); + } + } + for (var i in object.prototype) { + // make sure we don't touch properties that were synthetized + if (object.prototype.__lookupGetter__(i)) { + continue; + } + var prop = object.prototype[i]; + if (TKUtils.objectIsFunction(prop)) { + prop.displayName = TKUtils.createDisplayName(class_name, i); + } + } +}; + +TKUtils.createDisplayName = function (className, methodName) { + return className + '.' + methodName + '()'; +}; + +TKUtils.buildElement = function (elementData) { + // nothing to do if we don't have useful data + if (!elementData || !elementData.type) { + return null; + } + // + var element = null; + switch (elementData.type) { + case "emptyDiv": + element = document.createElement("div"); + break; + case "container": + element = document.createElement("div"); + for (var i=0; i < elementData.children.length; i++) { + element.appendChild(TKUtils.buildElement(elementData.children[i])); + } + break; + case "image": + element = document.createElement("img"); + element.src = elementData.src; + break; + case "text": + element = document.createElement("div"); + var p = document.createElement("p"); + p.innerText = elementData.text; + element.appendChild(p); + break; + default: + element = document.createElement(elementData.type); + element.innerHTML = elementData.content; + } + // add optional id + if (elementData.id) { + element.id = elementData.id; + } + // add optional class + if (elementData.className) { + element.className = elementData.className; + } + + // wrap in optional link + if (elementData.link){ + var subElement = element; + element = document.createElement("a"); + element.href = elementData.link; + element.target = "_blank"; + element.appendChild(subElement); + } + + return element; +}; + +/** + * Creates a DOM event. + * + * @param {String} eventType The event type. + * @param {Element} relatedTarget The optional related target for this event. + * + * @returns {Event} The event. + */ +TKUtils.createEvent = function (eventType, relatedTarget) { + var event = document.createEvent('Event'); + event.initEvent(eventType, true, true); + event.relatedTarget = relatedTarget; + return event; +}; + +/** + * Indicates whether a node is in some other node's subtree. + * + * @param {Node} childNode The alleged child node. + * @param {Node} allegedParentNode The alleged parent node. + * + * @returns {bool} Whether childNode is a child of allegedParentNode. + */ +TKUtils.isNodeChildOfOtherNode = function (childNode, allegedParentNode) { + var node = childNode.parentNode; + while (node !== null) { + if (node === allegedParentNode) { + return true; + break; + } + node = node.parentNode; + } + return false; +}; + +TKUtils.setupDisplayNames(TKUtils, 'TKUtils'); + +/* ==================== TKRect ==================== */ + +/** + * The top left corner of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectTopLeftCorner = 0; +/** + * The middle point on the top edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectMiddleOfTopEdge = 1; +/** + * The top right corner of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectTopRightCorner = 2; +/** + * The middle point on the right edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectMiddleOfRightEdge = 3; +/** + * The bottom right corner of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectBottomRightCorner = 4; +/** + * The middle point on the bottom edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectMiddleOfBottomEdge = 5; +/** + * The bottom left corner of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectBottomLeftCorner = 6; +/** + * The middle point on the left edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectMiddleOfLeftEdge = 7; +/** + * The center of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectCenter = 8; +/** + * The top edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectTopEdge = 9; +/** + * The right edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectRightEdge = 10; +/** + * The bottom edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectBottomEdge = 11; +/** + * The left edge of a rectangle. + * @constant + * @type int + * @private + */ +const TKRectLeftEdge = 12; + +/** + * @class + * + *

The TKRect provides some utilities to deal with a rectangle data type, allowing to obtain coordinates of the rectangle's points + * of interest as {@link TKPoint} objects and its edges as {@link TKSegment} objects, or obtaining a rectangle resulting in the union of several others.

+ * + * @since TuneKit 1.0 + * + * @param {float} x The x coordinate. + * @param {float} y The y coordinate. + * @param {float} width The width. + * @param {float} height The height. + */ +function TKRect (x, y, width, height) { + /** + * The x coordinate. + * @type float + */ + this.x = x || 0; + /** + * The y coordinate. + * @type float + */ + this.y = y || 0; + /** + * The width. + * @type float + */ + this.width = width || 0; + /** + * The height. + * @type float + */ + this.height = height || 0; +}; + +/** + * @private + * Provides the coordinates of a given point of interest. + * + * @param {int} index The point of interest. + * + * @returns {TKPoint} The point at the given point of interest. + */ +TKRect.prototype.pointAtPosition = function (index) { + var point; + if (index == TKRectTopLeftCorner) { + point = new TKPoint(this.x, this.y); + } + else if (index == TKRectMiddleOfTopEdge) { + point = new TKPoint(this.x + this.width / 2, this.y); + } + else if (index == TKRectTopRightCorner) { + point = new TKPoint(this.x + this.width, this.y); + } + else if (index == TKRectMiddleOfRightEdge) { + point = new TKPoint(this.x + this.width, this.y + this.height / 2); + } + else if (index == TKRectBottomRightCorner) { + point = new TKPoint(this.x + this.width, this.y + this.height); + } + else if (index == TKRectMiddleOfBottomEdge) { + point = new TKPoint(this.x + this.width / 2, this.y + this.height); + } + else if (index == TKRectBottomLeftCorner) { + point = new TKPoint(this.x, this.y + this.height); + } + else if (index == TKRectMiddleOfLeftEdge) { + point = new TKPoint(this.x, this.y + this.height / 2); + } + else if (index == TKRectCenter) { + point = new TKPoint(this.x + this.width / 2, this.y + this.height / 2); + } + return point; +}; + +/** + * @private + * Provides the segment for a given edge. + * + * @param {int} index The edge. + * + * @returns {TKSegment} The segment for the given edge. + */ +TKRect.prototype.edge = function (index) { + var edge; + if (index == TKRectTopEdge) { + edge = new TKSegment(this.pointAtPosition(TKRectTopLeftCorner), this.pointAtPosition(TKRectTopRightCorner)); + } + else if (index == TKRectRightEdge) { + edge = new TKSegment(this.pointAtPosition(TKRectTopRightCorner), this.pointAtPosition(TKRectBottomRightCorner)); + } + else if (index == TKRectBottomEdge) { + edge = new TKSegment(this.pointAtPosition(TKRectBottomLeftCorner), this.pointAtPosition(TKRectBottomRightCorner)); + } + else if (index == TKRectLeftEdge) { + edge = new TKSegment(this.pointAtPosition(TKRectTopLeftCorner), this.pointAtPosition(TKRectBottomLeftCorner)); + } + return edge; +}; + +/** + * Returns a {@link TKRect} from a rectangle returned by the Node.getBoundingClientRect method. + * + * @param {ClientRect} rect The CSS client rectangle. + * + * @returns {TKRect} The equivalent rectangle as a TuneKit data type. + */ +TKRect.rectFromClientRect = function (rect) { + return new TKRect(rect.left, rect.top, rect.width, rect.height); +}; + +/** + * @private + * Returns a {@link TKRect} encompassing the union of a list of other rectangles. + * + * @param {Array} rects The various rectangles we'd like the union of. + * + * @returns {TKRect} The rectangle encompassing the union of a list of the provided rectangles. + */ +TKRect.rectFromUnionOfRects = function (rects) { + if (rects.length < 1) { + return new TKRect(); + } + var union = rects[0]; + var rect; + for (var i = 1; i < rects.length; i++) { + rect = rects[i]; + union.x = Math.min(union.x, rect.x); + union.y = Math.min(union.y, rect.y); + union.width = Math.max(union.width, rect.x + rect.width); + union.height = Math.max(union.height, rect.y + rect.height); + } + return union; +}; + +/* ==================== TKPoint ==================== */ + +/** + * @private + * @class + * + *

The TKPoint provides a TuneKit data type to deal with points in 2D space and some utilities to work with them, such as figuring out + * the distance between two points.

+ * + * @since TuneKit 1.0 + * + * @param {float} x The x coordinate. + * @param {float} y The y coordinate. + */ +function TKPoint (x, y) { + /** + * The x coordinate. + * @type float + */ + this.x = x || 0; + /** + * The y coordinate. + * @type float + */ + this.y = y || 0; +}; + +/** + * Provides the distance between this point and another. + * + * @param {TKPoint} aPoint The point to which we'd like to figure out the distance. + * + * @returns {float} The distance between the receiver the provided point. + */ +TKPoint.prototype.distanceToPoint = function (aPoint) { + return Math.sqrt(Math.pow(aPoint.x - this.x, 2) + Math.pow(aPoint.y - this.y, 2)); +}; + +/* ==================== TKSegment ==================== */ + +/** + * @class + * @private + * + *

The TKSegment provides a TuneKit data type to deal with segments in 2D space and some utilities to work with them, such as figuring out + * the shortest distance between a segment and a point.

+ * + * @since TuneKit 1.0 + * + * @param {TKPoint} a The first extremity of the segment. + * @param {TKPoint} b The other extremity of the segment. + */ +function TKSegment (a, b) { + /** + * The first extremity of the segment. + * @type TKPoint + */ + this.a = a; + /** + * The other extremity of the segment. + * @type TKPoint + */ + this.b = b; + this.ab = new TKPoint(b.x - a.x, b.y - a.y); + /** + * The segment's length. + * @type float + */ + this.length = b.distanceToPoint(a); +}; + +// XXX: this only deals with horizontal and vertical lines +TKSegment.prototype.crossPoint = function (c) { + return (this.a.y == this.b.y) ? new TKPoint(c.x, this.a.y) : new TKPoint(this.a.x, c.y); +}; + +/** + * Computes the shortest distance between this segment and the given point. + * + * @param {TKPoint} aPoint + * + * @returns {float} The shortest distance between this segment and the given point. + */ +TKSegment.prototype.distanceToPoint = function (aPoint) { + var d; + var cross_point = this.crossPoint(aPoint); + // is it inside the segment? + if (cross_point.distanceToPoint(this.a) + cross_point.distanceToPoint(this.b) == this.length) { + d = aPoint.distanceToPoint(cross_point); + } + else { + d = Math.min(aPoint.distanceToPoint(this.a), aPoint.distanceToPoint(this.b)); + } + return d; +}; + +/* ================= Debugging ======================== */ + +var DEBUG = false; + +function debug(msg) { + if (window.DEBUG !== undefined && window.DEBUG) { + console.log("DEBUG: " + msg); + } +}; +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/** + * @class + * + *

The TKClass function will process a constructor function and set up its inheritance chain, synthetize + * a number of its instance properties and mix in additional capabilities based properties defined on + * that function. The supported properties are:

+ * + *
    + *
  • inherits – the superclass
  • + *
  • includes – an Array of modules to pull in
  • + *
  • synthetizes – an Array of properties to synthetize
  • + *
+ * + *

For instance, consider the following class declaration:

+ * + *
+// extends MySuperClass
+MyClass.inherits = MySuperClass;
+
+// mixes in the TKEventTriage and TKPropertyTriage modules
+MyClass.includes = [TKEventTriage, TKPropertyTriage]; 
+
+// synthetizes the .foo and .bar properties
+MyClass.synthetizes = ['foo', 'bar'];
+
+function MyClass () {
+  // constructor code goes here
+};
+
+// process properties set up on the MyClass constructor
+TKClass(MyClass);
+ *  
+ * + *

Synthetization is fully automated as long as the class that wishes to offer synthetized properties follows + * the following rules:

+ * + *
    + *
  • say the class wishes to synthetize the property .foo
  • + *
  • if the class chooses to define a getter method, it must be defined as getFoo on its prototype + *
  • if the class chooses to define a setter method, it must be defined as setFoo on its prototype + *
  • the class must define an instance variable ._foo which is the internal object that the class is responsible to update if either a setter is specified
  • + *
+ * + *

So our previous class declaration could be extended as follows:

+ * + *
+function MyClass () {
+  this._foo = '';
+};
+
+// custom setter for .foo, the getter is not specified
+// and TKClass() will automatically create it
+MyClass.prototype.setFoo = function (newFooValue) {
+  this._foo = newFooValue;
+};
+
+// custom getter for .foo, the setter is not specified
+// and TKClass() will automatically create it
+MyClass.prototype.getBar = function (newFooValue) {
+  return 'Hello ' + this._foo;
+};
+ *  
+ * + * @since TuneKit 1.0 + * + * @constructor + * @param theClass {Object} The class. + */ + +function TKClass (theClass) { + // check out if we have inheritance set up, otherwise, make TKObject the default superclass + if (TKUtils.objectIsUndefined(theClass.inherits) && theClass !== TKObject) { + theClass.inherits = TKObject; + } + + // check out if we have mixins + if (theClass.includes) { + TKClass.mixin(theClass.prototype, theClass.includes); + } + + // synthetizes properties defined locally + var properties = (theClass.synthetizes) ? theClass.synthetizes : []; + // now synthetize + for (var i = 0; i < properties.length; i++) { + TKClass.synthetizeProperty(theClass.prototype, properties[i], true); + } + + // synthetizes properties by compiling them up the inheritance chain + var aClass = theClass; + var properties = []; + while (aClass.inherits) { + aClass = aClass.inherits; + if (aClass.synthetizes) { + properties = aClass.synthetizes.concat(properties); + } + } + // now synthetize + for (var i = 0; i < properties.length; i++) { + TKClass.synthetizeProperty(theClass.prototype, properties[i], false); + } + + // go through each method and save its name as a custom property + // that we'll use later in TKObject.callSuper() + for (var i in theClass.prototype) { + // make sure we don't touch properties that were synthetized + if (theClass.prototype.__lookupGetter__(i)) { + continue; + } + var prop = theClass.prototype[i]; + if (TKUtils.objectIsFunction(prop)) { + prop._class = theClass; + prop._name = i; + prop.displayName = TKUtils.createDisplayName(theClass.name, i); + } + } + + // inherit from the superclass + // default to TKObject if nothing is specified + if (theClass !== TKObject) { + theClass.prototype.__proto__ = theClass.inherits.prototype; + } +}; + +TKClass.synthetizeProperty = function (object, propertyName, isPropertyInherited) { + var camel_ready = propertyName.charAt(0).toUpperCase() + propertyName.substr(1); + var getter_name = 'get' + camel_ready; + var setter_name = 'set' + camel_ready; + // check on function availability + var has_getter = TKUtils.objectHasMethod(object, getter_name); + var has_setter = TKUtils.objectHasMethod(object, setter_name); + + // if we have neither a getter or a setter, then do nothing + // unless the property is defined locally + if (!isPropertyInherited && !(has_getter || has_setter)) { + return; + } + + // assign the setter function if we have one + if (has_setter) { + var specified_setter_function = function (newValue) { + object[setter_name].call(this, newValue); + this.notifyPropertyChange(propertyName); + }; + specified_setter_function.displayName = 'Specified setter for .' + propertyName + ' on ' + object.constructor.name; + object.__defineSetter__(propertyName, specified_setter_function); + } + // otherwise just assign to _propertyName + else { + var default_setter_function = function (newValue) { + this['_' + propertyName] = newValue; + this.notifyPropertyChange(propertyName); + }; + default_setter_function.displayName = 'Default setter for .' + propertyName + ' on ' + object.constructor.name; + object.__defineSetter__(propertyName, default_setter_function); + } + + // assign the getter function if we have one + if (has_getter) { + object.__defineGetter__(propertyName, object[getter_name]); + } + // otherwise just return _propertyName + else { + var default_getter_function = function () { + return this['_' + propertyName]; + }; + default_getter_function.displayName = 'Default getter for .' + propertyName + ' on ' + object.constructor.name; + object.__defineGetter__(propertyName, default_getter_function); + } +}; + +TKClass.mixin = function (target, sources) { + for (var i = 0; i < sources.length; i++) { + TKUtils.copyPropertiesFromSourceToTarget(sources[i], target); + } +}; + +TKUtils.setupDisplayNames(TKClass, 'TKClass'); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/** + * @class + * @name Element + * @description Extensions to the DOM Core
Element interface. + * @since TuneKit 1.0 + */ + +/* ==================== Element Extensions ==================== */ + +/** + * Indicates whether the element has a given class name within its class attribute. + * + * @param {String} className The CSS class name. + * @returns {bool} Whether the element has this class name within its class attribute. + * @memberOf Element.prototype + */ +Element.prototype.hasClassName = function (className) { + return new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)').test(this.className); +}; + +/** + * Adds the given class name to the element's class attribute if it's not already there. + * + * @param {String} className The CSS class name. + * @memberOf Element.prototype + */ +Element.prototype.addClassName = function (className) { + if (!this.hasClassName(className)) { + this.className = [this.className, className].join(' '); + } +}; + +/** + * Removes the given class name from the element's class attribute if it's there. + * + * @param {String} className The CSS class name. + * @memberOf Element.prototype + */ +Element.prototype.removeClassName = function (className) { + if (this.hasClassName(className)) { + var curClasses = this.className; + this.className = curClasses.replace(new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', 'g'), ' '); + } +}; + +/** + * Adds the given class name to the element's class attribute if it's not there, or removes it if it's already set. + * + * @param {String} className The CSS class name. + * @memberOf Element.prototype + */ +Element.prototype.toggleClassName = function (className) { + this[this.hasClassName(className) ? 'removeClassName' : 'addClassName'](className); +}; + +/** + * Removes all the children from an element. + * + * @memberOf Element.prototype + */ +// XXX: should this be on Node? +Element.prototype.removeAllChildren = function () { + while (this.firstChild) { + this.removeChild(this.firstChild); + } +}; + +/** + * Returns true if the element has the given child node + * FIXME: should this be on Node? + * + * @param {Element} child The child to search for + * @memberOf Element.prototype + */ +Element.prototype.hasChild = function (child) { + for (var i=0; i < this.childNodes.length; i++) { + if (this.childNodes[i] === child) { + return true; + } + } + return false; +}; + +/** + * Applies a transition definition to the element, allowing the transition to be reversed. If this method is called + * within a {@link TKTransaction}, the transition will only be commited when the transaction is completed. + * + * @param {TKTransitionDefinition} transitionDefinition The transition applied to the element. + * @param {bool} reversed Indicates whether the transition is to be applied in reverse. + */ +Element.prototype.applyTransition = function (definition, reversed) { + // nothing to do if we have no definition + if (definition === null) { + return; + } + // create a TKTransition from the definition + var transition = new TKTransition(definition); + // this view will be the target + transition.target = this; + // revert from / to values as instructed + if (reversed) { + var from = transition.from; + transition.from = transition.to; + transition.to = from; + } + // set up base properties, if any + if (definition.base) { + for (var i = 0; i < definition.base.length; i += 2) { + this.style.setProperty(definition.base[i], definition.base[i+1], ''); + } + } + // start the transition + transition.start(); +}; + +Element.prototype.getBounds = function () { + return TKRect.rectFromClientRect(this.getBoundingClientRect()); +}; + +Element.prototype.isNavigable = function () { + var is_navigable = false; + if (this._controller !== undefined && this._controller !== null && this._controller.navigableElements.indexOf(this) !== -1) { + var style = window.getComputedStyle(this); + is_navigable = ( + style.display != 'none' && style.visibility != 'hidden' && + !this.hasClassName(TKSpatialNavigationManagerInactiveCSSClass) + ); + } + return is_navigable; +}; + +TKUtils.setupDisplayNames(Element, 'Element'); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +var TKEventTriage = {}; + +TKEventTriage.handleEvent = function (event) { + // first call the super class method that we may be overriding otherwise + if (this instanceof TKObject) { + this.callSuper(event); + } + // + var type = event.type; + var methodName = 'handle' + type.charAt(0).toUpperCase() + type.substr(1); + if (TKUtils.objectHasMethod(this, methodName)) { + this[methodName](event); + } +}; + +TKUtils.setupDisplayNames(TKEventTriage, 'TKEventTriage'); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/* ==================== Constants ==================== */ + +const TKObjectPropertyChanged = 'handlePropertyChange'; + +/* ==================== TKObject ==================== */ + +/** + * @class + * + *

The TKObject class is the base class for all TuneKit objects and provides a way to receive and trigger + * notifications when a JavaScript property changes.

+ * + *

Observing a property on an object is done through the + * {@link #addPropertyObserver} method, specifying the property to observe as well as the object that will + * receive the notifications of the property change. Likewise, an object can stop observing such changes using + * the {@link #removePropertyObserver} method. When a property value changes, the author needs to call the + * {@link #notifyPropertyChange} method so that registered observers will be notified. Note that synthetized + * properties will automatically trigger notifications when changed, so in this case, setters need not + * manually call {@link #notifyPropertyChange}.

+ * + *

Finally, TKObject also provides the {@link #callSuper} method to call the superclass's implementation + * of an overload method.

+ * + * @since TuneKit 1.0 + */ +function TKObject () { + this.observedProperties = {}; +}; + +/* ==================== Method overriding ==================== */ + +/** + * This method calls the object's superclass implementation of the current method + */ +TKObject.prototype.callSuper = function () { + // figure out what function called us + var caller = TKObject.prototype.callSuper.caller; + // if that function is a constructor, we call the parent class's constructor + if (TKUtils.objectHasMethod(caller, 'inherits')) { + caller.inherits.apply(this, arguments); + } + // otherwise we look at that function name in the parent prototype + else { + var parent = caller._class.inherits.prototype; + var method_name = caller._name; + if (TKUtils.objectHasMethod(parent, method_name)) { + return parent[method_name].apply(this, arguments); + } + } +}; + +/* ==================== Observing ==================== */ + +/** + * Indicates whether this object has registered observers for this property + * + * @param {String} propertyName The property that may be observed. + * + * @returns {bool} Whether this object has registered observers for this property + * @private + */ +TKObject.prototype.isPropertyObserved = function (propertyName) { + return !TKUtils.objectIsUndefined(this.observedProperties[propertyName]); +}; + +/** + * Adds an observer for the named property on this object. In case an existing + * combination of the observer and property is already registered, this method + * is a no-op. + * + * @param {String} propertyName The property to observe. + * @param {Object} observer The object that will be notified when the property is changed. + * @param {String} methodName The optional method name that will be called on the observer when the property is changed. + * If this property is not provided, the observer must implement the {@link TKPropertyValueChange} protocol. + */ +TKObject.prototype.addPropertyObserver = function (propertyName, observer, methodName) { + // create the array for this property if it's not already there + if (!this.isPropertyObserved(propertyName)) { + this.observedProperties[propertyName] = new Array(); + } + // do nothing if we already have this observer registered + else if (this.observedProperties[propertyName].indexOf(observer) > -1) { + return; + } + // now, add the observer to the observer array for this property if valid + var methodName = methodName || TKObjectPropertyChanged; + if (TKUtils.objectHasMethod(observer, methodName)) { + this.observedProperties[propertyName].push({ + observer: observer, + methodName : methodName + }); + } +}; + +/** + * Removes the observer for the named property on this object. In case an existing + * combination of the observer and property is not already registered, this method + * is a no-op. + * + * @param {String} propertyName The observed property. + * @param {Object} observer The object that was notified when the property changed. + * + * @returns {bool} Whether an observer was removed + */ +TKObject.prototype.removePropertyObserver = function (propertyName, observer) { + // do nothing if this property is not observed + if (!this.isPropertyObserved(propertyName)) { + return false; + } + // now get the observer's index in the array + var observers = this.observedProperties[propertyName]; + var observer_index = observers.indexOf(observer); + // remove the observer if it was registered + if (observer_index > -1) { + observers.splice(observer_index, 1); + } + // let the user know whether we succeeded + return (observer_index > -1); +}; + +/** + * Triggers a notification that the given property on this object has changed. + * For synthesized properties, this is called automatically upon setting the + * property. For methods that update an instance variable that is not synthesized, + * {@link #notifyPropertyChange} has to be called manually so that observers are notified. + * + * @param {String} propertyName The observed property. + */ +TKObject.prototype.notifyPropertyChange = function (propertyName) { + // do nothing if this property is not observed + if (!this.isPropertyObserved(propertyName)) { + return; + } + // now, go through each observer for this property and notify them + var observers = this.observedProperties[propertyName]; + for (var i = 0; i < observers.length; i++) { + var observer = observers[i]; + observer.observer[observer.methodName](this, propertyName); + } +}; + +/** + * Calls a method on this object after a delay, allowing any number of optional extra arguments to be + * passed after the first two mandatory ones. + * + * @param {String} methodName The method name to be called. + * @param {int} delay The delay in miliseconds. + * + * @returns {int} The timeout that can be used to call clearTimeout. + */ +TKObject.prototype.callMethodNameAfterDelay = function (methodName, delay) { + var _this = this; + var args = Array.prototype.slice.call(arguments, 2); + var generated_function = function () { + _this[methodName].apply(_this, args); + }; + generated_function.displayName = TKUtils.createDisplayName(this.constructor.name, methodName); + return setTimeout(generated_function, delay); +}; + +/** + * @class + * @name TKPropertyValueChange + * @since TuneKit 1.0 + */ + +/** + * Invoked when a property on an observed object has been changed. + * + * @name handlePropertyChange + * @function + * + * @param {Object} observedObject The observed object + * @param {String} propertyName The observed property's name as a string + * @memberOf TKPropertyValueChange.prototype + */ + +TKClass(TKObject, 'TKObject'); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/** + * @class + * @name TKTransitionDelegate + * @since TuneKit 1.0 + */ + +/** + * Invoked when a transition has completed. + * + * @name transitionDidComplete + * @function + * + * @param {TKTransition} theTransition The transition that just completed. + * @memberOf TKTransitionDelegate.prototype + */ + +const TKTransitionDidCompleteDelegate = 'transitionDidComplete'; + +const TKTransitionDefaults = { + duration : 0.5, + delay : 0, + removesTargetUponCompletion : false, + revertsToOriginalValues : false +}; + +const TKTransitionStyles = ['-webkit-transition-property', '-webkit-transition-duration', '-webkit-transition-timing-function', '-webkit-transition-delay', '-webkit-transition']; + +/* ==================== TKTransition ==================== */ + +/** + * @class + * + *

The TKTransition class allows to create a synchronized change of one or more property values on a + * {@link Element} instance or any DOM element.

+ * + *

First, the user sets the {@link #target} for the transition, + * identifying the target element, and second the set of {@link #properties}, in the form of an Array + * of CSS properties for the element. Then the {@link #to} and optional + * {@link #from} value arrays are provided to define what values will be used for the transition. Each item in the + * {@link #from} and {@link #to} arrays matches the item at the same index in the {@link #properties} array, and the same + * applies to the {@link #duration} property, which can also be a single value shared for all transitioned properties.

+ * + *

Finally, once the properties on the transition are all set, the {@link #start} method must be called so that the + * transition is started. Note that it is possible to group transitions within a {@link TKTransaction} and set a default + * set of transition properties within a transaction using the {@link TKTransaction.defaults} static property.

+ * + *

The following example shows how to make a transition that fades an element in as it animates from the right side of the screen:

+ * +
+new TKTransition({
+  target : anElement,
+  properties : ['opacity', '-webkit-transform'];
+  from : [0, 'translate(320px, 0)'],
+  to : [1, 'translate(0, 0)']
+  duration : 0.5;
+}).start();
+
+ * + *

Note that properties of a {@link TKTransition} object can be passed as a batch to the {@link TKTransition} constructor + * as an anonymous object. This also allows reuse of a set of parameters across several transitions. Also, a set of pre-baked + * transitions exist can be easily applied to an element with the {@link Element#applyTransition} method.

+ * + * @since TuneKit 1.0 + */ +function TKTransition (params) { + // set up defaults + /** + * The transition target. + * @type Element + */ + this.target = null; + /** + * The set of properties that will be transitioned. The properties are CSS properties of the targeted Element. + * @type Array + */ + this.properties = null; + /** + * The set of durations in seconds, each duration matching a property in the {@link #properties} array. + * Note that it's possible to specify a single value instead of an array to use the same duration for + * all properties. + * @type Object + */ + this.duration = null; + /** + * The set of delays in seconds, each delay matching a property in the {@link #properties} array. + * Note that it's possible to specify a single delay instead of an array to use the same delay for + * all properties. + * @type Object + */ + this.delay = null; + /** + * Optional list of values to start the transition from. Each value in this array must match the property + * at the same index in the {@link #properties} array. + * @type Array + */ + this.from = null; + /** + * Required list of values to transition to. Each value in this array must match the property + * at the same index in the {@link #properties} array. + * @type Array + */ + this.to = null; + /** + * The set of timing functions, each timing function matching a property in the {@link #properties} + * array. Note that it's possible to specify a single timing function instead of an array to use the + * same timing function for all properties. + * @type Object + */ + this.timingFunction = null; + /** + * The delegate object that implements the {@link TKTransitionDelegate} protocol. + * @type Object + */ + this.delegate = null; + /** + * Indicates whether the target needs to be removed once the transition completes. Defaults to false. + * @type bool + */ + this.removesTargetUponCompletion = null; + /** + * Indicates whether the target needs to reset the property that are transitioned to their original values + * once the transition completes. Defaults to false. + * @type bool + */ + this.revertsToOriginalValues = null; + // + this.defaultsApplied = false; + this.archivedStyles = null; + this.archivedValues = []; + // import params + TKUtils.copyPropertiesFromSourceToTarget(params, this); +}; + +/* ==================== Dealing with defaults ==================== */ + +TKTransition.prototype.applyDefaults = function () { + if (this.defaultsApplied) { + return; + } + // + for (var i in TKTransitionDefaults) { + if (this[i] === null) { + this[i] = TKTransitionDefaults[i]; + } + } + // + this.defaultsApplied = true; +}; + +/* ==================== Archiving the transition styles ==================== */ + +TKTransition.prototype.getTargetStyle = function () { + // if (this.target.style === null) { + // this.target.setAttribute('style', 'foo: bar'); + // } + return this.target.style; +}; + +TKTransition.prototype.archiveTransitionStyles = function () { + // do nothing if we already have archived styles in this run session + if (this.archivedStyles !== null) { + return; + } + // iterate all TKTransitionStyles and archive them + this.archivedStyles = []; + var style = this.getTargetStyle(); + for (var i = 0; i < TKTransitionStyles.length; i++) { + this.archivedStyles.push(style.getPropertyValue(TKTransitionStyles[i])); + } +}; + +TKTransition.prototype.restoreTransitionStyles = function () { + var style = this.getTargetStyle(); + // iterate all TKTransitionStyles and restore them + for (var i = 0; i < TKTransitionStyles.length; i++) { + style.setProperty(TKTransitionStyles[i], this.archivedStyles[i], ''); + } + // reset archived styles + this.archivedStyles = null; +}; + +/* ==================== Archiving the base values ==================== */ + +TKTransition.prototype.archiveBaseValues = function () { + // do nothing if we don't need to archive base values + if (!this.revertsToOriginalValues) { + return; + } + var style = this.getTargetStyle(); + for (var i = 0; i < this.properties.length; i++) { + this.archivedValues.push(style.getPropertyValue(this.properties[i])); + } +}; + +TKTransition.prototype.restoreBaseValues = function () { + var style = this.getTargetStyle(); + for (var i = 0; i < this.properties.length; i++) { + style.setProperty(this.properties[i], this.archivedValues[i], null); + } +}; + +/* ==================== Starting the transition ==================== */ + +/** + * Starts the transition. + */ +TKTransition.prototype.start = function () { + // if we have an active transaction, just add to it + if (TKTransaction.openTransactions > 0) { + TKTransaction.addTransition(this); + return; + } + // otherwise, we'll just get it going + this.applyDefaults(); + if (this.from === null) { + this.applyToState(); + } + else { + this.applyFromState(); + var _this = this; + setTimeout(function () { + _this.applyToState(); + }, 0); + } +}; + +/* ==================== Applying the "from" state ==================== */ + +TKTransition.prototype.applyFromState = function () { + // do nothing if we have no "from" state specified + if (this.from === null) { + return; + } + // + this.applyDefaults(); + this.archiveTransitionStyles(); + var style = this.getTargetStyle(); + style.webkitTransitionDuration = 0; + for (var i = 0; i < this.properties.length; i++) { + style.setProperty(this.properties[i], this.from[i], ''); + } +}; + +/* ==================== Applying the "to" state ==================== */ + +TKTransition.prototype.applyToState = function () { + // first, make sure we have defaults applied if some + // properties are not explicitely set on our transition + this.applyDefaults(); + + // and that we archive the transition styles to be reverted + this.archiveTransitionStyles(); + + // and that we archive the original values + this.archiveBaseValues(); + + // now compile the styles needed for this transition + this.cssProperties = []; + var transition_styles = []; + for (var i = 0; i < this.properties.length; i++) { + var property = this.properties[i]; + // do nothing if we already have an animation defined for this + if (this.cssProperties.indexOf(property) > -1) { + continue; + } + // else, set up the CSS style for this transition + var duration = (TKUtils.objectIsArray(this.duration)) ? this.duration[i] : this.duration; + var timing = (TKUtils.objectIsArray(this.timingFunction)) ? this.timingFunction[i] : this.timingFunction; + var delay = (TKUtils.objectIsArray(this.delay)) ? this.delay[i] : this.delay; + transition_styles.push([property, duration + 's', timing, delay + 's'].join(' ')); + // and remember we are animating this property + this.cssProperties.push(property); + } + + var style = this.getTargetStyle(); + for (var i = 0; i < this.properties.length; i++) { + style.setProperty(this.properties[i], this.to[i], ''); + } + + // set up the transition styles + style.webkitTransition = transition_styles.join(', '); + + // register for events to track transition completions + this.target.addEventListener('webkitTransitionEnd', this, false); + this.completedTransitions = 0; +}; + +/* ==================== Tracking transition completion ==================== */ + +// XXX: we won't be getting an event for properties that have the same value in the to +// state, so we'll need to do a little work to track css properties that won't really transition +TKTransition.prototype.handleEvent = function (event) { + // do nothing if that event just bubbled from our target's sub-tree + if (event.currentTarget !== this.target) { + return; + } + + // update the completion counter + this.completedTransitions++; + + // do nothing if we still have running transitions + if (this.completedTransitions != this.cssProperties.length) { + return; + } + + // the counter reached our properties count, fire up the delegate + if (TKUtils.objectHasMethod(this.delegate, TKTransitionDidCompleteDelegate)) { + this.delegate[TKTransitionDidCompleteDelegate](this); + } + + // remove from the tree if instructed to do so + if (this.removesTargetUponCompletion) { + this.target.parentNode.removeChild(this.target); + } + // otherwise, restore transition styles + else { + this.restoreTransitionStyles(); + } + + // restore original values if instructed to do so + if (this.revertsToOriginalValues) { + this.restoreBaseValues(); + } +}; + +TKClass(TKTransition); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/* ==================== TKTransaction ==================== */ + +/** + * @class + * + *

A transaction allows to run a variety of transitions in sync, no matter in what function or JavaScript run loop + * the transition itself was applied. Transactions can be nested, and a transaction is only truly commited when there + * are no other open transactions. In other words, there must be as many calls to {@link TKTransaction.begin} as there + * are calls to {@link TKTransaction.commit} before any transition in one of those transactions can be applied. + * + * @since TuneKit 1.0 + */ +var TKTransaction = { + transitions : [], + openTransactions : 0, + /** + * The set of default properties that will be applied to any {@link TKTransition} until the next call to {@link TKTransaction.commit}. + * Any of the properties that can be applied to a {@link TKTransition} can be applied to this object. + * @type Object + */ + defaults : {}, + defaultsStates : [] +}; + +/** + * Begins a new transaction and makes it the current transaction. + */ +TKTransaction.begin = function () { + // reset the group if we're starting fresh + if (this.openTransactions == 0) { + this.transitions = []; + this.defaults = {}; + } + // otherwise, archive the current state of defaults + else { + this.defaultsStates.push(this.defaults); + // XXX: should we restore defaults here as well? + } + // increase the number of open transactions + this.openTransactions++; +}; + +/** + * Add Transition + * + * @private + */ +TKTransaction.addTransition = function (transition) { + // first, apply the transaction defaults to the transitions + for (var i in this.defaults) { + if (transition[i] === null) { + transition[i] = this.defaults[i]; + } + } + // and add the transition to our array + this.transitions.push(transition); +}; + +/** + * Closes the current transaction. + */ +TKTransaction.commit = function () { + // do nothing if we have no open transactions + if (this.openTransactions == 0) { + return; + } + // decrease the number of open transactions + this.openTransactions--; + // if we still have open transactions, just + // restore the previous defaults state + if (this.openTransactions != 0) { + this.defaults = this.defaultsStates.pop(); + return; + } + // otherwise, it's time to shake and bake, we'll apply the + // "from" states directly and the "to" states immediately + // after in a new run loop so that the "from" styles have + // been resolved first + var transitions = this.transitions; + for (var i = 0; i < transitions.length; i++) { + transitions[i].applyFromState(); + } + setTimeout(function () { + for (var i = 0; i < transitions.length; i++) { + transitions[i].applyToState(); + } + }, 0); +}; + +TKUtils.setupDisplayNames(TKTransaction, 'TKTransaction'); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/** + * @class + * + * A virtual class that allows the definition of pre-baked transitions that can be used as parameter + * for the {@link Element#applyTransition} method. In reality, any object that provides the type of + * properties instances of this class offers can be used with that method. + * + * @name TKTransitionDefinition + * @since TuneKit 1.0 + */ + +/** + * @name TKTransitionDefinition.prototype + * @property {Array} base A set of property / value pairs that are applied to the element as the transition starts. The properties + * listed there are not supposed to be transitioned. If you wish to set a from state for a property that gets transitioned, use + * the {@link #properties} and {@link from} properties instead. + * @property {Array} properties The set of properties that will be transitioned. The properties are CSS properties + * of the element that will be transitioned using this definition. + * @property {Array} from Optional list of values to start the transition from. Each value in this array must match the property + * at the same index in the {@link #properties} array. + * @property {Array} to Required list of values to transition to. Each value in this array must match the property + * at the same index in the {@link #properties} array. + */ + +/** + * Fades out. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionDissolveOut = { + properties : ['opacity'], + from : [1], + to : [0] +}; + +/** + * Fades in. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionDissolveIn = { + properties : ['opacity'], + from : [0], + to : [1] +}; + +/** + * Fades in while scaling up to identity scale. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionZoomIn = { + properties : ['opacity', '-webkit-transform'], + from : [0, 'scale(0.2)'], + to : [1, 'scale(1)'] +}; + +/** + * Fades out while scaling down to identity scale. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionZoomOut = { + properties : ['opacity', '-webkit-transform'], + from : [0, 'scale(1.2)'], + to : [1, 'scale(1)'] +}; + +/** + * Fades in while rotating from the right. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionCrossSpinRight = { + properties : ['opacity', '-webkit-transform'], + from : [0, 'rotate(20deg)'], + to : [1, 'rotate(0)'] +}; + +/** + * Fades in while rotating from the left. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionCrossSpinLeft = { + properties : ['opacity', '-webkit-transform'], + from : [0, 'rotate(-20deg)'], + to : [1, 'rotate(0)'] +}; + +/** + * Scale transition scaling in. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionScaleIn = { + base : ['z-index', 1], + properties : ['-webkit-transform'], + from : ['scale(0.01)'], + to : ['scale(1)'] +}; + +/** + * Scale transition scaling out. + * @constant + * @type TKTransitionDefinition + */ +const TKViewTransitionScaleOut = { + base : ['z-index', 1], + properties : ['-webkit-transform'], + from : ['scale(1)'], + to : ['scale(0.01)'] +}; +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/* ==================== Constants ==================== */ + +const TKAnimatorLinearType = 0; +const TKAnimatorSplinesType = 1; +const TKAnimatorInvalidArgsException = 2; + +const TKAnimatorAnimationDidIterate = 'animationDidIterate'; +const TKAnimatorAnimationDidEnd = 'animationDidEnd'; + +/* ==================== TKAnimator ==================== */ + +function TKAnimator (duration, delegate, spline) { + // check validity of arguments number + // if (arguments.length != 2 && arguments.length != 3 && arguments.length != 7) { + // throw TKAnimatorInvalidArgsException; + // return false; + // } + // init some base properties + this.ready = false; + this.animating = false; + this.timer = null; + // handle arguments + this.duration = duration; // ms + this.delegate = delegate; + // check we have the required delegation method + // if (!TKUtils.objectHasMethod(this.delegate, TKAnimatorAnimationDidIterate)) { + // return; + // } + // handle splines arguments, if available + if (arguments.length >= 3) { + this.type = TKAnimatorSplinesType; + this.x1 = spline[0]; + this.y1 = spline[1]; + this.x2 = spline[2]; + this.y2 = spline[3]; + this.init(); + } + else { // linear animation + this.type = TKAnimatorLinearType; + } + this.ready = true; +}; + +TKAnimator.prototype.init = function () { + // calculate the polynomial coefficients + this.cx = 3 * this.x1; + this.bx = 3 * (this.x2 - this.x1) - this.cx; + this.ax = 1 - this.cx - this.bx; + this.cy = 3 * this.y1; + this.by = 3 * (this.y2 - this.y1) - this.cy; + this.ay = 1 - this.cy - this.by; + // compute points + var numberOfPoints = (this.duration / 1000) * 240; + this.curve = new Array(numberOfPoints); + var dt = 1.0 / ( numberOfPoints - 1 ); + for (var i = 0; i < numberOfPoints; i++) { + var t = i * dt; + this.curve[i] = { + x : (this.ax * Math.pow(t, 3)) + (this.bx * Math.pow(t, 2)) + (this.cx * t), + y : (this.ay * Math.pow(t, 3)) + (this.by * Math.pow(t, 2)) + (this.cy * t) + }; + } +}; + +TKAnimator.prototype.start = function () { + if (!this.ready) { + var _this = this; + this.timer = setTimeout(function () { _this.start() }, 0); + return; + } + this.animating = true; + this.lastIndex = 0; + this.startTime = (new Date()).getTime(); + this.iterate(); +}; + +TKAnimator.prototype.stop = function () { + this.animating = false; + clearTimeout(this.timer); +}; + +TKAnimator.prototype.iterate = function () { + var ellapsedTime = (new Date()).getTime() - this.startTime; + if (ellapsedTime < this.duration) { + var x = ellapsedTime / this.duration; + // handle splines case + if (this.type == TKAnimatorSplinesType) { + var y = 0; + for (var i = this.lastIndex; i < this.curve.length; i++) { + var point = this.curve[i]; + if (point.x >= x && i > 0) { + var previous_point = this.curve[i - 1]; + if ((x - previous_point.x) < (point.x - x)) { + this.lastIndex = i - 1; + y = previous_point.y; + } + else { + this.lastIndex = i; + y = point.y; + } + break; + } + } + } + this.delegate[TKAnimatorAnimationDidIterate]((this.type == TKAnimatorSplinesType) ? y : x); + var _this = this; + this.timer = setTimeout(function () { _this.iterate() }, 0); + } + else { + this.delegate[TKAnimatorAnimationDidIterate](1); + if (TKUtils.objectHasMethod(this.delegate, TKAnimatorAnimationDidEnd)) { + this.delegate[TKAnimatorAnimationDidEnd](); + } + this.animating = false; + } +}; + +/* ==================== CLASS CREATION ==================== */ + +TKClass(TKAnimator); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +// --------------------------------------------------- +// A two dimensional sliding view +// --------------------------------------------------- + +/** + * @class + * @name TKSlidingViewData + * @since TuneKit 1.0 + */ + +/** + * @name TKSlidingViewData.prototype + * + * @property {int} sideElementsVisible The number of elements on each side of the selected page. If the {@link #incrementalLoading} property is set to + * true, this specifies the number of elements in the DOM on each side as others beyond that range are removed from the tree. Otherwise, this + * specifies the threshold after which elements in either direction from the selected page get the sliding-view-element-hidden CSS class applied. + * + * @property {int} distanceBetweenElements The distance in pixels between the center points of each page, essentially the overall width of each page. + * + * @property {int} sideOffsetBefore Any additional margin in pixels to the left of each page. + * + * @property {int} sideOffsetAfter Any additional margin in pixels to the right of each page. + * + * @property {Array} elements The elements for the sliding view. + * + * @property {bool} incrementalLoading Indicates whether elements in the sliding view's DOM are added and removed gradually as we browse through it, or all + * available in one go, which is the default. If you are populating a sliding view with a large amount of content, you should consider setting this property + * to true in order to ease memory constraints and enhance performance. + * + * @property {bool} loops Whether we loop through pages. Defaults to false. + * + */ + +// data source method names +const TKSlidingViewNumberOfElements = 'slidingViewNumberOfElements'; +const TKSlidingViewElementAtIndex = 'slidingViewElementAtIndex'; + +// delegate method names +const TKSlidingViewStyleForItemAtIndex = 'slidingViewStyleForItemAtIndex'; +const TKSlidingViewDidSelectActiveElement = 'slidingViewDidSelectActiveElement'; +const TKSlidingViewDidFocusElementAtIndex = 'slidingViewDidFocusElementAtIndex'; +const TKSlidingViewDidBlurElementAtIndex = 'slidingViewDidBlurElementAtIndex'; +const TKSlidingViewDidHideElementAtIndex = 'slidingViewDidHideElementAtIndex'; // TODO: XXX +const TKSlidingViewWillUnhideElementAtIndex = 'slidingViewWillUnhideElementAtIndex'; // TODO: XXX + +const TKSlidingViewDidHoverElementAtIndex = 'slidingViewDidHoverElementAtIndex'; +const TKSlidingViewDidUnhoverElementAtIndex = 'slidingViewDidUnhoverElementAtIndex'; + +// css protocol +const TKSlidingViewCSSContainerClass = 'sliding-view'; +const TKSlidingViewCSSElementClass = 'sliding-view-element'; +const TKSlidingViewCSSFocusedClass = 'sliding-view-element-focused'; +const TKSlidingViewCSSSideBeforeClass = 'sliding-view-element-before'; +const TKSlidingViewCSSSideAfterClass = 'sliding-view-element-after'; +const TKSlidingViewCSSStagedBeforeClass = 'sliding-view-element-staged-before'; +const TKSlidingViewCSSStagedAfterClass = 'sliding-view-element-staged-after'; +const TKSlidingViewCSSHiddenClass = 'sliding-view-element-hidden'; + +// orientations +const TKSlidingViewOrientationHorizontal = 'horizontal'; +const TKSlidingViewOrientationVertical = 'vertical'; + +TKSlidingView.synthetizes = ['dataSource', + 'delegate', + 'activeElement', + 'activeElementIndex', // the index of the middle/focused element + 'orientation', // whether the view should be horizontal or vertical + 'interactive', // whether or not this view will listen for mouse events + 'sideOffsetBefore', // gap between focused element and the elements before it + 'sideOffsetAfter', // gap between focused element and the elements after it + 'distanceBetweenElements', // general distance between elements in the layout + 'sideElementsVisible', // the number of elements that are considered visible before and after the focus + 'pageControl', // a TKPageControl object that should be linked to this slider (not needed) + 'incrementalLoading', // whether or not the elements should be added to the view as required + 'loops', // if true, the sliding view loops continuously + 'raiseHoverEvents', // if true, the sliding view will use the Hover and Unhover delegate methods + 'numberOfElements']; + +function TKSlidingView (element) { + this.callSuper(); + // these defaults look ok for elements about 180 square + this._activeElementIndex = 0; + this._orientation = TKSlidingViewOrientationHorizontal; + this._interactive = true; + this._sideOffsetBefore = 160; + this._sideOffsetAfter = 160; + this._distanceBetweenElements = 25; + this._sideElementsVisible = 4; + this._pageControl = null; + this._incrementalLoading = false; + this._loops = false; + this._raiseHoverEvents = false; + + this._elements = []; + + if (element) { + this.element = element; + } else { + // create the element we'll use as a container + this.element = document.createElement("div"); + } + this.element.addClassName(TKSlidingViewCSSContainerClass); +} + +TKSlidingView.prototype.init = function () { + + if (!this.dataSource || + !TKUtils.objectHasMethod(this.dataSource, TKSlidingViewNumberOfElements) || + !TKUtils.objectHasMethod(this.dataSource, TKSlidingViewElementAtIndex)) { + return; + } + + var numElements = this.numberOfElements; + + if (this._incrementalLoading) { + // add enough to be visible + this.bufferElements(); + } else { + // add all the elements + for (var i=0; i < numElements; i++) { + var el = this.dataSource[TKSlidingViewElementAtIndex](this, i); + el.addClassName(TKSlidingViewCSSElementClass); + el._needsAppending = true; + this._elements[i] = el; + el._slidingViewIndex = i; + if (this._interactive) { + el.addEventListener("click", this, false); + } + if (this._raiseHoverEvents) { + el.addEventListener("mouseover", this, false); + el.addEventListener("mouseout", this, false); + } + } + } + + this.layout(true); +}; + +TKSlidingView.prototype.setPageControl = function (newPageControl) { + this._pageControl = newPageControl; + this._pageControl.deferCurrentPageDisplay = true; + this._pageControl.delegate = this; + this._pageControl.currentPage = this._activeElementIndex; +}; + +TKSlidingView.prototype.getActiveElement = function () { + return this._elements[this._activeElementIndex]; +}; + +TKSlidingView.prototype.setActiveElementIndex = function (newActiveElementIndex) { + + if ((this._loops || (newActiveElementIndex >= 0 && newActiveElementIndex < this.numberOfElements)) && + newActiveElementIndex != this._activeElementIndex) { + + var needsForcedLayout = (this._activeElementIndex === undefined); + + // call delegate to inform blur of current active element + if (!needsForcedLayout && TKUtils.objectHasMethod(this.delegate, TKSlidingViewDidBlurElementAtIndex)) { + this.delegate[TKSlidingViewDidBlurElementAtIndex](this, this._activeElementIndex); + } + + if (newActiveElementIndex < 0) { + this._activeElementIndex = (this.numberOfElements + newActiveElementIndex) % this.numberOfElements; + } else { + this._activeElementIndex = newActiveElementIndex % this.numberOfElements; + } + + // if there is a page control, tell it to update + if (this._pageControl) { + this._pageControl.currentPage = newActiveElementIndex; + } + + this.bufferElements(); + this.layout(needsForcedLayout); + + // call delegate to inform focus of new active element + // this needs to be done at the very end so we're use any code depending on + // .activeElement actually works since we need elements buffered + if (TKUtils.objectHasMethod(this.delegate, TKSlidingViewDidFocusElementAtIndex)) { + this.delegate[TKSlidingViewDidFocusElementAtIndex](this, this._activeElementIndex); + } + } +}; + +TKSlidingView.prototype.getNumberOfElements = function () { + if (this.dataSource) { + return this.dataSource[TKSlidingViewNumberOfElements](this); + } else { + return 0; + } +}; + +TKSlidingView.prototype.getElementAtIndex = function (index) { + return this._elements[index]; +}; + +// this method loads the elements that are necessary for +// display, and removes the ones that are not needed +TKSlidingView.prototype.bufferElements = function () { + if (this._incrementalLoading) { + var numElements = this.numberOfElements; + for (var i=0; i < numElements; i++) { + var offset = this._activeElementIndex - i; + var absOffset = Math.abs(offset); + if (this._loops) { + // FIXME: check this! doesn't seem right + var offset2 = offset + ((offset < 0) ? numElements : -numElements); + var absOffset2 = Math.abs(offset2); + if (absOffset2 <= this._sideElementsVisible) { + offset = offset2; + absOffset = absOffset2; + } + } + if (absOffset <= this._sideElementsVisible) { + if (!this._elements[i]) { + var el = this.dataSource[TKSlidingViewElementAtIndex](this, i); + el.addClassName(TKSlidingViewCSSElementClass); + el._needsAppending = true; + this._elements[i] = el; + el._slidingViewIndex = i; + if (this._interactive) { + el.addEventListener("click", this, false); + } + if (this._raiseHoverEvents) { + el.addEventListener("mouseover", this, false); + el.addEventListener("mouseout", this, false); + } + + } + } else { + // element isn't needed + if (this._elements[i]) { + this.element.removeChild(this._elements[i]); + this._elements[i] = null; + } + } + } + } +}; + +TKSlidingView.prototype.layout = function (forceLayout) { + var numElements = this.numberOfElements; + + for (var i=0; i < numElements; i++) { + var offset = this._activeElementIndex - i; + var absOffset = Math.abs(offset); + if (this._loops) { + // FIXME: check this! doesn't seem right + var offset2 = offset + ((offset < 0) ? numElements : -numElements); + var absOffset2 = Math.abs(offset2); + if (absOffset2 <= this._sideElementsVisible) { + offset = offset2; + absOffset = absOffset2; + } + } + + var element = this._elements[i]; + + if (!element) { + // only layout elements we need to + continue; + } + + // loaded elements might not yet have been added to the document + // this makes them appear in the right place + if (element._needsAppending) { + this.element.appendChild(element); + element._needsAppending = false; + } + + // Three cases for layout: + // - element is inside (visible) + // - element is just outside (one element outside each edge - called "staged") + // - element is really outside (we call this "hidden" and inform delegate) + + var transform = null; + if (absOffset <= this._sideElementsVisible) { + if (offset > 0) { + if (this._orientation == TKSlidingViewOrientationHorizontal) { + transform = "translate3d(" + (-1 * (absOffset * this._distanceBetweenElements + this._sideOffsetBefore)) + "px, 0, 0)"; + } else { + transform = "translate3d(0, " + (-1 * (absOffset * this._distanceBetweenElements + this._sideOffsetBefore)) + "px, 0)"; + } + this.applySlidingClass(element, TKSlidingViewCSSSideBeforeClass); + } else if (offset < 0) { + if (this._orientation == TKSlidingViewOrientationHorizontal) { + transform = "translate3d(" + (absOffset * this._distanceBetweenElements + this._sideOffsetAfter) + "px, 0, 0)"; + } else { + transform = "translate3d(0, " + (absOffset * this._distanceBetweenElements + this._sideOffsetAfter) + "px, 0)"; + } + this.applySlidingClass(element, TKSlidingViewCSSSideAfterClass); + } else { + transform = "translate3d(0, 0, 0)"; + this.applySlidingClass(element, TKSlidingViewCSSFocusedClass); + } + element.style.webkitTransform = transform; + element.style.opacity = 1; + } else if (absOffset == (this._sideElementsVisible + 1)) { + // FIXME: this is wrong!! should be staged classes - worried this will break things if I fix it + if (offset > 0) { + if (this._orientation == TKSlidingViewOrientationHorizontal) { + transform = "translate3d(" + (-1 * (absOffset * this._distanceBetweenElements + this._sideOffsetBefore)) + "px, 0, 0)"; + } else { + transform = "translate3d(0, " + (-1 * (absOffset * this._distanceBetweenElements + this._sideOffsetBefore)) + "px, 0)"; + } + this.applySlidingClass(element, TKSlidingViewCSSSideBeforeClass); + } else { + if (this._orientation == TKSlidingViewOrientationHorizontal) { + transform = "translate3d(" + (absOffset * this._distanceBetweenElements + this._sideOffsetAfter) + "px, 0, 0)"; + } else { + transform = "translate3d(0, " + (absOffset * this._distanceBetweenElements + this._sideOffsetAfter) + "px, 0)"; + } + this.applySlidingClass(element, TKSlidingViewCSSSideAfterClass); + } + element.style.webkitTransform = transform; + element.style.opacity = 0; + } else if (absOffset > this._sideElementsVisible || forceLayout) { + if (offset > 0) { + if (this._orientation == TKSlidingViewOrientationHorizontal) { + transform = "translate3d(" + (-1 * (absOffset * this._distanceBetweenElements + this._sideOffsetBefore)) + "px, 0, 0)"; + } else { + transform = "translate3d(0, " + (-1 * (absOffset * this._distanceBetweenElements + this._sideOffsetBefore)) + "px, 0)"; + } + } else { + if (this._orientation == TKSlidingViewOrientationHorizontal) { + transform = "translate3d(" + (absOffset * this._distanceBetweenElements + this._sideOffsetAfter) + "px, 0, 0)"; + } else { + transform = "translate3d(0, " + (absOffset * this._distanceBetweenElements + this._sideOffsetAfter) + "px, 0)"; + } + } + this.applySlidingClass(element, TKSlidingViewCSSHiddenClass); + element.style.webkitTransform = transform; + element.style.opacity = 0; + } + // now see if we have any over-ride styles to apply from the delegate + if (TKUtils.objectHasMethod(this.delegate, TKSlidingViewStyleForItemAtIndex)) { + override_styles = this.delegate[TKSlidingViewStyleForItemAtIndex](this, i); + for (var j = 0; j < override_styles.length; j++) { + var override_style = override_styles[j]; + element.style.setProperty(override_style[0], override_style[1], ''); + } + } + } +}; + +TKSlidingView.prototype.applySlidingClass = function (element, className) { + element.removeClassName(TKSlidingViewCSSFocusedClass); + element.removeClassName(TKSlidingViewCSSSideBeforeClass); + element.removeClassName(TKSlidingViewCSSSideAfterClass); + element.removeClassName(TKSlidingViewCSSStagedBeforeClass); + element.removeClassName(TKSlidingViewCSSStagedAfterClass); + element.removeClassName(TKSlidingViewCSSHiddenClass); + + element.addClassName(className); +}; + +TKSlidingView.prototype.handleEvent = function (event) { + switch (event.type) { + case "click": + this.handleClick(event); + break; + case "mouseover": + this.handleMouseover(event); + break; + case "mouseout": + this.handleMouseout(event); + break; + default: + debug("unhandled event type in TKSlidingView: " + event.type); + } +}; + +TKSlidingView.prototype.handleClick = function (event) { + // The event.target should have an _slidingViewIndex property. If + // not, then go up to parent + var target = event.target; + while (target && TKUtils.objectIsUndefined(target._slidingViewIndex)) { + target = target.parentNode; + } + if (!target) { + return; + } + + if (target._slidingViewIndex == this.activeElementIndex) { + if (TKUtils.objectHasMethod(this.delegate, TKSlidingViewDidSelectActiveElement)) { + this.delegate[TKSlidingViewDidSelectActiveElement](this, this._activeElementIndex); + } + } else { + // Check if the click was before or after the focused element. + if (target._slidingViewIndex < this.activeElementIndex) { + if (this._loops && target._slidingViewIndex == 0) { + this.activeElementIndex = 0; + } else { + this.activeElementIndex--; + } + } else { + if (this._loops && target._slidingViewIndex == this.numberOfElements - 1) { + this.activeElementIndex = this.numberOfElements - 1; + } else { + this.activeElementIndex++; + } + } + } +}; + +TKSlidingView.prototype.handleMouseover = function (event) { + // The event.target should have an _slidingViewIndex property. If + // not, then go up to parent + var target = event.target; + while (target && TKUtils.objectIsUndefined(target._slidingViewIndex)) { + target = target.parentNode; + } + if (!target) { + return; + } + + if (TKUtils.objectHasMethod(this.delegate, TKSlidingViewDidHoverElementAtIndex)) { + this.delegate[TKSlidingViewDidHoverElementAtIndex](this, target._slidingViewIndex); + } +}; + +TKSlidingView.prototype.handleMouseout = function (event) { + // The event.target should have an _slidingViewIndex property. If + // not, then go up to parent + var target = event.target; + while (target && TKUtils.objectIsUndefined(target._slidingViewIndex)) { + target = target.parentNode; + } + if (!target) { + return; + } + + if (TKUtils.objectHasMethod(this.delegate, TKSlidingViewDidUnhoverElementAtIndex)) { + this.delegate[TKSlidingViewDidUnhoverElementAtIndex](this, target._slidingViewIndex); + } +}; + +// delegate for page control +TKSlidingView.prototype.pageControlDidUpdateCurrentPage = function (control, newPageIndex) { + if (control === this._pageControl) { + this.activeElementIndex = newPageIndex; + this._pageControl.updateCurrentPageDisplay(); + } +}; + + +TKClass(TKSlidingView); + +/* ====================== Datasource helper ====================== */ + +function TKSlidingViewDataSourceHelper(data, incrementalLoading) { + this.data = data; + this.incrementalLoading = incrementalLoading; + this.elements = []; +}; + +TKSlidingViewDataSourceHelper.prototype.slidingViewNumberOfElements = function(view) { + if (this.data) { + return this.data.length; + } else { + return 0; + } +}; + +TKSlidingViewDataSourceHelper.prototype.slidingViewElementAtIndex = function(view, index) { + if (!this.data || index >= this.data.length) { + return null; + } + var element = this.elements[index]; + if (!element) { + var source = this.data[index]; + element = TKUtils.buildElement(source); + } + if (!this.incrementalLoading) { + this.elements[index] = element; + } + return element; +}; + +/* ====================== Declarative helper ====================== */ + +TKSlidingView.buildSlidingView = function(element, data) { + if (TKUtils.objectIsUndefined(data) || !data || data.type != "TKSlidingView") { + return null; + } + + var slidingView = new TKSlidingView(element); + if (!TKUtils.objectIsUndefined(data.elements)) { + slidingView.dataSource = new TKSlidingViewDataSourceHelper(data.elements, data.incrementalLoading); + } + + TKSlidingView.synthetizes.forEach(function(prop) { + if (prop != "dataSource" && prop != "delegate") { + if (!TKUtils.objectIsUndefined(data[prop])) { + slidingView[prop] = data[prop]; + } + } + }); + + return slidingView; +}; + +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +// --------------------------------------------------- +// A page control implementation +// --------------------------------------------------- + +/** + * @class + * @name TKPageControlData + * @since TuneKit 1.0 + */ + +/** + * @name TKPageControlData.prototype + * + * @property {int} distanceBetweenPageIndicators The distance in pixels between the center points of each indicator, essentially the overall + * width of each indicator. + * + * @property {bool} showPageElements Indicates whether individual elements for each page should be shown, or only the pill. Defaults to false= this._numPages) { + return; + } + + this._currentPage = newCurrentPage; + + if (TKUtils.objectHasMethod(this.delegate, TKPageControlDidUpdateCurrentPage)) { + this.delegate[TKPageControlDidUpdateCurrentPage](this, this._currentPage); + } + + if (!this._deferCurrentPageDisplay) { + this.updateCurrentPageDisplay(); + } +}; + +TKPageControl.prototype.updateCurrentPageDisplay = function () { + var indicatorElement = this.dataSource[TKPageControlIndicatorElement](this); + indicatorElement.style.webkitTransform = "translate(" + (this._currentPage * this._distanceBetweenPageIndicators) + "px, 0px)"; +}; + +TKPageControl.prototype.handleEvent = function (event) { + switch (event.type) { + case "mousedown": + this.handleDragBegan(event); + break; + case "mousemove": + this.handleDragMove(event); + break; + case "mouseup": + this.handleDragEnded(event); + break; + case "click": + this.handleClick(event); + break; + default: + debug("unhandled event type in TKPageControl: " + event.type); + } +}; + +TKPageControl.prototype.setupMouseInteraction = function () { + // in case we have page elements, let's look at the position of the first element as + // the minimum x value that we'll use for interactions from then on + if (this._showPageElements) { + // get the elements + var page_elements = this.element.querySelectorAll('.' + TKPageControlCSSPageElementClass); + var page_element_bounds = page_elements[0].getBounds(); + this.minX = page_element_bounds.x + (page_element_bounds.width - this._distanceBetweenPageIndicators) / 2; + } + // otherwise, use the bounds of the container + else { + this.minX = this.element.getBounds().x; + } + // now convert this value into the coordinate system of our element + var point = window.webkitConvertPointFromPageToNode(this.element, new WebKitPoint(this.minX, 0)); + this.minX = point.x; +}; + +TKPageControl.prototype.pageIndexAtXY = function (x, y) { + var point = window.webkitConvertPointFromPageToNode(this.element, new WebKitPoint(x, y)); + var page_index = Math.floor((point.x - this.minX) / this._distanceBetweenPageIndicators); + return Math.max(Math.min(page_index, this._numPages), 0); +}; + +TKPageControl.prototype.handleClick = function (event) { + // set up the mouse interaction + this.setupMouseInteraction(); + // mark that we are interacting + // XXX: should we really be doing this? This class is not being removed it seems. + this.element.addClassName("interactive"); + // set the current page based on that right from the get go + this.currentPage = this.pageIndexAtXY(event.clientX, event.clientY); +}; + +TKPageControl.prototype.handleDragBegan = function (event) { + if (!this._allowsDragging) { + return; + } + // ensure we cancel the default web page behavior for a dragging interaction + event.preventDefault(); + // set up the mouse interaction + this.setupMouseInteraction(); + // mark that we are interacting + this.element.addClassName("interactive"); + // set the current page based on that right from the get go + this.currentPage = this.pageIndexAtXY(event.clientX, event.clientY); + // track mouse moves + window.addEventListener("mousemove", this, false); + window.addEventListener("mouseup", this, false); +}; + +TKPageControl.prototype.handleDragMove = function (event) { + // ensure we cancel the default web page behavior for a dragging interaction + event.preventDefault(); + // update the page + this.currentPage = this.pageIndexAtXY(event.clientX, event.clientY); +}; + +TKPageControl.prototype.handleDragEnded = function (event) { + // ensure we cancel the default web page behavior for a dragging interaction + event.preventDefault(); + // mark that we are not interacting anymore + this.element.removeClassName("interactive"); + // stop tracking events + window.removeEventListener("mousemove", this); + window.removeEventListener("mouseup", this); +}; + +TKClass(TKPageControl); + +/* ====================== Datasource helper ====================== */ + +function TKPageControlDataSourceHelper(data) { + this.data = data; + this.pageElement = null; + this.indicatorElement = null; +}; + +TKPageControlDataSourceHelper.prototype.pageControlPageElement = function(pageControl) { + if (!this.data) { + return null; + } + if (!this.pageElement) { + this.pageElement = TKUtils.buildElement(this.data.pageElement); + } + return this.pageElement; +}; + +TKPageControlDataSourceHelper.prototype.pageControlIndicatorElement = function(pageControl) { + if (!this.data) { + return null; + } + if (!this.indicatorElement) { + this.indicatorElement = TKUtils.buildElement(this.data.indicatorElement); + } + return this.indicatorElement; +}; + +/* ====================== Declarative helper ====================== */ + +TKPageControl.buildPageControl = function(element, data) { + if (TKUtils.objectIsUndefined(data) || !data || data.type != "TKPageControl") { + return null; + } + + var pageControl = new TKPageControl(element); + + pageControl.dataSource = new TKPageControlDataSourceHelper(data); + + TKPageControl.synthetizes.forEach(function(prop) { + if (prop != "dataSource" && prop != "delegate") { + if (!TKUtils.objectIsUndefined(data[prop])) { + pageControl[prop] = data[prop]; + } + } + }); + + return pageControl; +}; + +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +TKController.inherits = TKObject; +TKController.synthetizes = ['view', 'navigableElements', 'actions', 'outlets', 'scrollable', 'backButton', 'navigatesTo']; + +/** + * The hash in which we keep references to all controller instantiated throughout the lifecycle of the booklet. Use a controller's {@link #id} to + * access the controller for that id. + * @type Object + */ +TKController.controllers = {}; + +/** + * The fraction of the scrollable element's width or height that is being scrolled by in order to increment or decrement the scroll offset. + * @constant + * @type float + * @private + */ +const TKControllerScrollIncrementFraction = 0.75; +/** + * The time in miliseconds that the scrolling animation lasts. + * @constant + * @type int + * @private + */ +const TKControllerScrollDuration = 500; +/** + * The spline used for the scrolling animation. + * @constant + * @type Array + * @private + */ +const TKControllerScrollSpline = [0.211196, 0.811224, 0.641221, 0.979592]; +const TKControllerScrollDirectionUp = 0; +const TKControllerScrollDirectionDown = 1; +const TKControllerScrollDirectionLeft = 0; +const TKControllerScrollDirectionRight = 1; + +/** + * @class + * + *

The TKController class is the base class for all TuneKit controllers. Controllers are useful objects that control all the core functionalities of + * a screen or sub-screen: view-loading, interaction, navigation, etc.

+ * + * @extends TKObject + * @since TuneKit 1.0 + * + * @param {Object} data A hash of properties to use as this object is initialized. + */ +function TKController (data) { + this.callSuper(); + // + this.propertiesToRestoreOnLoad = []; + // synthetized property + this._view = null; + /** + * @name TKController.prototype + * @property {Array} navigableElements The complete list of all elements that can be navigated to within this controller and all of its sub-controllers. + * The contents of this array should not be directly manipulated, instead use the {@link #addNavigableElement} and {@link #removeNavigableElement} methods. + */ + this._navigableElements = []; + /** + * The controller directly containing this controller instance, null if the controller is not attached to any yet. + * @type TKController + */ + this.parentController = null; + // default transition styles for navigation + this.enforcesCustomTransitions = false; // whether we should use the custom transitions on ATV only + /** + * The animated transition to use for this controller's view when the controller becomes inactive. + * @type TKTransitionDefinition + */ + this.becomesInactiveTransition = TKViewTransitionDissolveOut; + /** + * The animated transition to use for this controller's view when the controller becomes active. + * @type TKTransitionDefinition + */ + this.becomesActiveTransition = TKViewTransitionDissolveIn; + // default properties + /** + * The unique id for this controller's view. This is the same string that will be used for the {@link #view}'s HTML id attribute, as well + * as a key in the {@link TKController.controllers} hash, and thus must be adequate for both uses. The controller's id is used in the view-loading mechanism, + * such that if there is an HTML file in the booklet's views/ directory that shares the same name, it is that file that is loaded to provide + * the view's content. + * @type String + */ + this.id = data.id; + /** + * A DOM element to be used as the view for this controller, which overrides the default view-loading mechanism in case it's set before the view is loaded. + * @type Element + * @private + */ + this.explicitView = null; + /** + * The name of the template to be used to create the view's content. If there is an HTML file in the templates/ directory with that name, the + * view is loaded by cloning the content of that file and replacing the ID with that provided by the {@link #id} property. + * @type String + */ + this.template = null; + /** + * A list of image URIs to preload. + * @type Array + */ + this.preloads = []; + this._navigatesTo = null; + this._actions = null; + this._outlets = null; + this._scrollable = null; + this._backButton = null; + /** + * The highlighted element within that controller. This is only unique to the view managed by this controller, and not to the entire booklet or even any + * controllers that might be contained within this controller. + * @type Element + * @private + */ + this.highlightedElement = null; + /** + * Indicates that the view has not appeared on screen yet. + * @type bool + * @private + */ + this.viewNeverAppeared = true; + /** + * Indicates that the view was fully processed. + * @type bool + * @private + */ + this.viewWasProcessed = false; + /** + * The CSS selector for the default scrollable element. If this value is non-null then the up and down keys scroll the element specified + * by the selector. + * @type String + */ + this.scrollableElement = null; + /** + * The animator managing the currently scrolling element. + * @type TKAnimator + * @private + */ + this.animator = new TKAnimator(TKControllerScrollDuration, null, TKControllerScrollSpline); + this.upScrollData = { + direction: TKControllerScrollDirectionUp, + animator: this.animator + } + this.downScrollData = { + direction: TKControllerScrollDirectionDown, + animator: this.animator + } + // copy properties + this.copyNonSynthetizedProperties(data); + // register controller + TKController.controllers[this.id] = this; +}; + +/** + * A utility method to get the controller from an Object that is either the {@link TKController#id} of a controller or a controller directly. + * + * @param {Object} stringOrControllerReference Either the {@link TKController#id} of a controller or a controller directly + * @returns {TKController} The controller. + */ +TKController.resolveController = function (stringOrControllerReference) { + return (TKUtils.objectIsString(stringOrControllerReference)) ? TKController.controllers[stringOrControllerReference] : stringOrControllerReference; +}; + +/** + * A utility method to copy all properties from another object onto the controller, ignoring any property that is synthetized. + * + * @param {Object} properties An object containing a set of properties to be copied across to the receiver. + * @private + */ +TKController.prototype.copyNonSynthetizedProperties = function (properties) { + for (var property in properties) { + // don't copy synthetized properties but track them for later + if (this.__lookupSetter__(property)) { + this.propertiesToRestoreOnLoad[property] = properties[property]; + continue; + } + this[property] = properties[property]; + } +}; + +/* ==================== Managing the View ==================== */ + +TKController.prototype.getView = function () { + // create the view if it's not set yet + if (this._view === null) { + this.loadView(); + } + return this._view; +}; + +TKController.prototype.setView = function (view) { + this.explicitView = view; +}; + +TKController.prototype.loadView = function () { + this.viewNeverAppeared = false; + // first, check if we have an element already defined + var view; + if (this.explicitView !== null) { + view = this.explicitView; + // check if node is already in the document + this.viewNeverAppeared = !TKUtils.isNodeChildOfOtherNode(view, document); + } + // check if our view already exists in the DOM + else { + view = document.getElementById(this.id); + } + // if not, load it from the views directory + if (view === null) { + this.viewNeverAppeared = true; + view = this.loadFragment('views', this.id); + // there was no such view available, try and see if we have a template available + if (view === null) { + if (this.template !== null) { + view = this.loadFragment('templates', this.template); + } + // no template, just create an empty
then + if (view === null) { + view = document.createElement('div'); + } + } + } + // make sure we know when the view is added to the document if it + // wasn't part of the DOM already + if (this.viewNeverAppeared) { + view.addEventListener('DOMNodeInsertedIntoDocument', this, false); + } + // set up the correct id on our view + view.id = this.id; + // link the view to our controller + view._controller = this; + // and remember our view + this._view = view; + // let our object perform more setup code + this.viewDidLoad(); + // do post-loading processing + this.processView(); + // + this.viewWasProcessed = true; +}; + +TKController.prototype.loadFragment = function (directory, id) { + var imported_fragment = null; + // + var request = new XMLHttpRequest(); + var failed = false; + request.open('GET', directory + '/' + id + '.html', false); + try { + request.send(); + } catch (err) { + // iTunes will throw an error if the request doesn't exist + // when using the booklet:// scheme + // Mark the error here so we can take the FAIL path below, which + // is actually what we want. + failed = true; + } + // everything went well + // XXX: we should do more work to differentitate between http:// and file:// URLs here + if (!failed && ((request.status <= 0 && request.responseText !== '') || request.status == 200)) { + // XXX: this is way dirty + var loaded_fragment = document.implementation.createHTMLDocument(); + loaded_fragment.write(request.responseText); + imported_fragment = document.importNode(loaded_fragment.getElementById(id), true); + } + return imported_fragment; +}; + +/** + * This method is called once the view has been loaded and allows the controller to post-process it. + */ +TKController.prototype.processView = function () { + var view = this._view; + // restore properties that have not been set yet since construction + this.restoreProperty('navigatesTo'); + this.restoreProperty('actions'); + this.restoreProperty('outlets'); + this.restoreProperty('backButton'); + this.restoreProperty('scrollable'); + // process highlightedElement + if (this.highlightedElement !== null && !(this.highlightedElement instanceof Element)) { + this.highlightedElement = this._view.querySelector(this.highlightedElement); + } + // process links + var links = view.querySelectorAll('a'); + for (var i = 0; i < links.length; i++) { + this.addNavigableElement(links[i]); + } + // process assets to pre-load + for (var i = 0; i < this.preloads.length; i++) { + new Image().src = this.preloads[i]; + } +}; + +TKController.prototype.restoreProperty = function (property) { + var value = this.propertiesToRestoreOnLoad[property]; + if (value !== undefined && this['_' + property] === null) { + this[property] = value; + } +}; + +TKController.prototype.getArchivedProperty = function (property) { + var archived_value; + try { + var archived_value = bookletController.archive.controllers[this.id][property]; + } + catch (e) {} + return archived_value; +}; + +/** + * Indicates whether the view the controller manages was loaded yet. + * + * @returns {bool} Whether the view was loaded yet. + */ +TKController.prototype.isViewLoaded = function () { + return (this._view !== null); +}; + +/* ==================== Dealing with the various properties ==================== */ + +/** + * @name TKController.prototype + * @property {Array} navigatesTo A list of objects defining elements to act as anchors to navigate to other controllers. Each object in the array is an + * ad-hoc object with selector and controller properties. The selector is a string describing a CSS selector used + * to match the element within the {@link #view} that will act as an anchor to navigate to the controller. The controller is either a string matching + * the {@link #id} of an existing controller or an reference to a {@link TKController}. + */ +TKController.prototype.setNavigatesTo = function (navigatesTo) { + if (navigatesTo === null) { + return; + } + // unregister the previous elements if we have any + if (this._navigatesTo !== null) { + for (var i = 0; i < this._navigatesTo.length; i++) { + var element = this._navigatesTo[i]; + element._navigationData = undefined; + this.removeNavigableElement(element); + } + } + // register the new elements + this._navigatesTo = []; + for (var i = 0; i < navigatesTo.length; i++) { + var item = navigatesTo[i]; + var element = this._view.querySelector(item.selector); + if (element) { + element._navigationData = item; + this._navigatesTo.push(element); + this.addNavigableElement(element); + } + } +}; + +/** + * @name TKController.prototype + * @property {Array} actions A list of objects defining elements to act as anchors to trigger a JavaScript callback. Each object in the array is an + * ad-hoc object with selector, action and, optionally, arguments properties. The selector is a + * string describing a CSS selector used to match the element within the {@link #view} that will act as a trigger for the action. The action + * specifies the function to call when the action is triggered, which is either a string matching the name of a method on this controller instance or + * a direct reference to a function. Optionally, the arguments property can be specified in order to provide a list of arguments to be passed + * to the callback when the action is triggered. + */ +TKController.prototype.setActions = function (actions) { + if (actions === null || this._actions === actions) { + return; + } + // unregister the previous elements if we have any + if (this._actions !== null) { + for (var i = 0; i < this._actions.length; i++) { + var element = this._actions[i]; + element._actionData = undefined; + this.removeNavigableElement(element); + } + } + // register the new elements + this._actions = []; + for (var i = 0; i < actions.length; i++) { + var item = actions[i]; + var element = this._view.querySelector(item.selector); + if (element) { + element._actionData = item; + this._actions.push(element); + this.addNavigableElement(element); + } + } +}; + +/** + * @name TKController.prototype + * @property {Array} outlets A list of objects defining elements to which we want to create an automatic reference on the controller instance. Each object in + * the array has a selector and a name property. The selector is a string describing a CSS selector used to match the + * element within the {@link #view} to which we want to create a reference. The name specifies the name of the JavaScript property that will be holding + * that reference on the controller instance. + */ +TKController.prototype.setOutlets = function (outlets) { + if (outlets === null) { + return; + } + // unregister the previous outlets if we have any + if (this._outlets !== null) { + for (var i = 0; i < this._outlets.length; i++) { + this[this._outlets[i]] = undefined; + } + } + // register the new outlets + for (var i = 0; i < outlets.length; i++) { + var item = outlets[i]; + this[item.name] = this._view.querySelector(item.selector); + } + this._outlets = outlets; +}; + +/** + * @name TKController.prototype + * @property {String} backButton A CSS selector that matches an element in the {@link #view} that acts as the back button. + */ +TKController.prototype.setBackButton = function (backButton) { + if (backButton === null) { + return; + } + // forget the old back button if we have one + if (this._backButton !== null) { + this._backButton._backButton = undefined; + // restore display type on ATV + if (IS_APPLE_TV) { + this._backButton.style.display = this._backButton._previousDisplayStyle; + } + this.removeNavigableElement(this._backButton); + } + // set up the new one + if (backButton !== null) { + var element = this._view.querySelector(backButton); + element._backButton = true; + // hide it on ATV + if (IS_APPLE_TV) { + element._previousDisplayStyle = element.style.display; + element.style.display = 'none'; + } + this.addNavigableElement(element); + this._backButton = element; + } +}; + +/* ==================== Notification Methods ==================== */ + +/** + * This method is called when the view has been fully loaded but not yet processed. Override this method in order to customize the content of the view. + */ +TKController.prototype.viewDidLoad = function () {}; +TKController.prototype.viewDidUnload = function () {}; + +TKController.prototype._viewWillAppear = function () {}; +/** + * This method is called when the view managed by this controller is about to appear on screen, probably after an animated transition. + */ +TKController.prototype.viewWillAppear = function () {}; + +TKController.prototype._viewDidAppear = function () {}; +/** + * This method is called when the view managed by this controller appeared on screen, probably after an animated transition. + */ +TKController.prototype.viewDidAppear = function () {}; + +TKController.prototype._viewWillDisappear = function () {}; +/** + * This method is called when the view managed by this controller is about to disappear from the screen, probably after an animated transition. + */ +TKController.prototype.viewWillDisappear = function () {}; + +TKController.prototype._viewDidDisappear = function () {}; +/** + * This method is called when the view managed by this controller has disappeared from the screen, probably after an animated transition. + */ +TKController.prototype.viewDidDisappear = function () {}; + +/* ==================== Event Handling ==================== */ + +/** + * Entry point for all event handling, since TKController implements the DOM EventListener protocol. This method may be subclassed + * but it is important to call the superclass's implementation of this method as essential event routing happens there. + * + * @param {Event} event The event. + */ +TKController.prototype.handleEvent = function (event) { + switch (event.type) { + case 'click' : + this.elementWasActivated(event.currentTarget); + break; + case 'highlight' : + this.elementWasHighlighted(event.currentTarget, event.relatedTarget); + break; + case 'unhighlight' : + this.elementWasUnhighlighted(event.currentTarget, event.relatedTarget); + break; + case 'mouseover' : + this.elementWasHovered(event.currentTarget); + break; + case 'mouseout' : + this.elementWasUnhovered(event.currentTarget); + break; + case 'DOMNodeInsertedIntoDocument' : + this.viewWasInsertedIntoDocument(event); + break; + } +}; + +/** + * Triggered when an element is activated by the user, no matter what the host's input methods are as TuneKit abstracts the interaction that yields + * an element's activation. This method may be subclassed but it is important to call the superclass's implementation of this method as navigation anchors, + * actions, etc. are handled in that method directly. + * + * @param {Element} element The element that was just activated. + */ +TKController.prototype.elementWasActivated = function (element) { + if (element._navigationData !== undefined) { + // pointer to the controller + var controller = TKController.resolveController(element._navigationData.controller); + // error if we have an undefined object + if (controller === undefined) { + console.error('TKController.elementWasActivated: trying to push an undefined controller'); + return; + } + // otherwise, navigate to it + TKSpatialNavigationManager.sharedManager.highlightElement(element); + TKNavigationController.sharedNavigation.pushController(controller); + } + else if (element._actionData !== undefined) { + TKSpatialNavigationManager.sharedManager.highlightElement(element); + // get the callback for this action + var callback = element._actionData.action; + // see if it's a string in which case we need to get the function dynamically + if (TKUtils.objectIsString(callback) && TKUtils.objectHasMethod(this, callback)) { + callback = this[element._actionData.action]; + } + // see if we have custom arguments + if (TKUtils.objectIsArray(element._actionData.arguments)) { + callback.apply(this, element._actionData.arguments); + } + // otherwise just call the callback + else { + callback.apply(this); + } + } + else if (element._backButton !== undefined) { + TKSpatialNavigationManager.soundToPlay = SOUND_EXIT; + TKSpatialNavigationManager.sharedManager.highlightElement(element); + TKNavigationController.sharedNavigation.popController(); + } + else if (element.localName == 'a' && IS_APPLE_TV) { + element.dispatchEvent(TKUtils.createEvent('click', null)); + } + else if (element._scrollableData !== undefined) { + this.scrollWithData(element._scrollableData); + } +}; + +/** + * Triggered when an element receives highlight. + * + * @param {Element} element The element that is newly being highlighted. + * @param {Element} previouslyHighlightedElement The element that previously was highlighted, or null if there was none. + */ +TKController.prototype.elementWasHighlighted = function (element, previouslyHighlightedElement) { +}; + +/** + * Triggered when an element loses highlight. + * + * @param {Element} element The element that is newly being highlighted. + * @param {Element} nextHighlightedElement The element that is going to be highlighted next, or null if there is none. + */ +TKController.prototype.elementWasUnhighlighted = function (element, nextHighlightedElement) { +}; + +/** + * Triggered when an element is hovered, which only happens when a mouse is present. + * + * @param {Element} element The element that is being hovered. + */ +TKController.prototype.elementWasHovered = function (element) { +}; + +/** + * Triggered when an element is not hovered any longer, which only happens when a mouse is present. + * + * @param {Element} element The element that is not hovered any longer. + */ +TKController.prototype.elementWasUnhovered = function (element) { +}; + +/** + * Triggered when the view is first inserted into the document. + */ +TKController.prototype.viewWasInsertedIntoDocument = function () { + this.viewNeverAppeared = false; +}; + +/** + * Indicates whether the receiver is a descendent of the controller passed as an argument. + * + * @param {TKController} purportedParentController The controller that we assume is a parent controller to the receiver. + * @returns {bool} Whether the controller is a descendent of the other controller passed as a parameter. + */ +TKController.prototype.isDescendentOfController = function (purportedParentController) { + var is_descendent = false; + var parent = this.parentController; + while (parent !== null) { + if (parent === purportedParentController) { + is_descendent = true; + break; + } + parent = parent.parentController; + } + return is_descendent; +}; + +/* ==================== Keyboard Navigation ==================== */ + +/** + * Adds an element within the controller's view to the list of navigable elements. Any element that is interactive should be registered as navigable, even + * when a mouse is available. + * + * @param {Element} element The element we wish to make navigable. + */ +TKController.prototype.addNavigableElement = function (element) { + // nothing to do if we already know about this element + if (this._navigableElements.indexOf(element) > -1) { + return; + } + // + if (!IS_APPLE_TV) { + element.addEventListener('click', this, false); + } + element.addEventListener('highlight', this, false); + element.addEventListener('unhighlight', this, false); + element._controller = this; + // + this._navigableElements.push(element); + // + TKSpatialNavigationManager.sharedManager.addNavigableElement(element); +}; + +/** + * Removes an element within the controller's view from the list of navigable elements. + * + * @param {Element} element The element we wish to remove from the navigable elements list. + */ +TKController.prototype.removeNavigableElement = function (element) { + // find the index for this element + var index = this._navigableElements.indexOf(element); + if (index < 0) { + return; + } + // + element.removeEventListener('click', this, false); + element.removeEventListener('highlight', this, false); + element.removeEventListener('unhighlight', this, false); + element._controller = undefined; + // remove elements from the tracking arrays + this._navigableElements.splice(index, 1); + // + TKSpatialNavigationManager.sharedManager.removeNavigableElement(element); +}; + +/** + * Allows to specify custom metrics for an element displayed on screen. This method is called by the spatial navigation manager when determining what the + * element to highlight is after the uses presses a directional key on the Apple remote. By default, the CSS metrics for the elements are used, but in + * certain cases the author may wish to use different metrics that are more logical for the navigation. Return null in order to specify that + * the element has no custom metrics. + * + * @param {Element} element The element which the spatial navigation manager is inspecting. + * @returns {TKRect} The custom metrics for the given element. + */ +TKController.prototype.customMetricsForElement = function (element) { + return null; +}; + +/** + * Allows the controller to provide the spatial navigation manager with a prefered element to highlight, overriding the default behavior of using CSS metrics. + * The default implementation returns undefined, which indicates that the automatic behavior should be used, while returning null + * means that there should be no element highlighted in the provided direction. + * + * @param {Element} currentElement The element that is currently highlighted. + * @param {int} direction The direction the user is navigation towards. + * @returns {Element} The preferred element to highlight in the provided direction. + */ +TKController.prototype.preferredElementToHighlightInDirection = function (currentElement, direction) { + return undefined; +}; + +// private method meant to be over-ridden by a controller sub-classes to provide a custom element +// to highlight, returning null means there's nothing custom to report +// XXX: we really need a better mechanism to do this stuff, having a private method for subclasses and one for instances is way dirty +TKController.prototype._preferredElementToHighlightInDirection = function (currentElement, direction) { + return undefined; +}; + +/* ==================== Scrolling ==================== */ + +TKController.prototype.setScrollable = function (scrollable) { + // remove all scrollable regions if we already had some set up + if (this._scrollable !== null) { + for (var i = 0; i < this._scrollable.length; i++) { + var element = this._scrollable[i]; + element._scrollableData = undefined; + this.removeNavigableElement(element); + } + } + // process scrollable regions + this._scrollable = []; + for (var i = 0; i < scrollable.length; i++) { + var scrollable_data = scrollable[i]; + // create an animator for this scrollable element + scrollable_data.animator = new TKAnimator(TKControllerScrollDuration, null, TKControllerScrollSpline); + // check if we have an up element + if (scrollable_data.up !== undefined) { + var up_button = this._view.querySelector(scrollable_data.up); + up_button._scrollableData = { + direction: TKControllerScrollDirectionUp, + target: scrollable_data.target, + animator: scrollable_data.animator + }; + this._scrollable.push(up_button); + this.addNavigableElement(up_button); + } + // check if we have a down element + if (scrollable_data.down !== undefined) { + var down_button = this._view.querySelector(scrollable_data.down); + down_button._scrollableData = { + direction: TKControllerScrollDirectionDown, + target: scrollable_data.target, + animator: scrollable_data.animator + }; + this._scrollable.push(down_button); + this.addNavigableElement(down_button); + } + // check if we have a left element + if (scrollable_data.left !== undefined) { + var left_button = this._view.querySelector(scrollable_data.left); + left_button._scrollableData = { + direction: TKControllerScrollDirectionLeft, + target: scrollable_data.target, + animator: scrollable_data.animator + }; + this._scrollable.push(left_button); + this.addNavigableElement(left_button); + } + // check if we have a right element + if (scrollable_data.right !== undefined) { + var right_button = this._view.querySelector(scrollable_data.right); + right_button._scrollableData = { + direction: TKControllerScrollDirectionRight, + target: scrollable_data.target, + animator: scrollable_data.animator + }; + this._scrollable.push(right_button); + this.addNavigableElement(right_button); + } + } +}; + +TKController.prototype.scrollWithData = function (scrollData) { + // stop any running animation for this scrollable region + scrollData.animator.stop(); + // get a pointer to the target element + var element = this._view.querySelector(scrollData.target); + // stop right there if there's no such element + if (!(element instanceof Element)) { + TKSpatialNavigationManager.soundToPlay = SOUND_LIMIT; + return; + } + // figure out which direction we're scrolling + var vertical_scrolling = (scrollData.direction == TKControllerScrollDirectionUp || scrollData.direction == TKControllerScrollDirectionDown); + // get the increment for this scroll + var increment = element[vertical_scrolling ? 'offsetHeight' : 'offsetWidth'] * TKControllerScrollIncrementFraction; + // get the start value + var start_value = element[vertical_scrolling ? 'scrollTop' : 'scrollLeft']; + // get the target value + var target_value; + if (scrollData.direction == TKControllerScrollDirectionUp) { + target_value = Math.max(element.scrollTop - increment, 0); + } + else if (scrollData.direction == TKControllerScrollDirectionDown) { + target_value = Math.min(element.scrollTop + increment, element.scrollHeight - element.offsetHeight); + } + else if (scrollData.direction == TKControllerScrollDirectionLeft) { + target_value = Math.max(element.scrollLeft - increment, 0); + } + else if (scrollData.direction == TKControllerScrollDirectionRight) { + target_value = Math.min(element.scrollLeft + increment, element.scrollWidth - element.offsetWidth); + } + // only run if we have different values + if (start_value == target_value) { + TKSpatialNavigationManager.soundToPlay = SOUND_LIMIT; + return; + } + // set the delegate + scrollData.animator.delegate = { + animationDidIterate : function (fraction) { + element[vertical_scrolling ? 'scrollTop' : 'scrollLeft'] = start_value + fraction * (target_value - start_value); + } + } + // start the animation + scrollData.animator.start(); + // play the move sound since we're scrolling + TKSpatialNavigationManager.soundToPlay = SOUND_MOVED; +}; + +TKController.prototype.scrollUp = function () { + this.upScrollData.target = this.scrollableElement; + this.scrollWithData(this.upScrollData); +}; + +TKController.prototype.scrollDown = function () { + this.downScrollData.target = this.scrollableElement; + this.scrollWithData(this.downScrollData); +}; + +/* ==================== Keyboard Navigation ==================== */ + +/** + * Indicates whether the controller is interested in providing event handling for the key with the given identifier. By default, this method returns + * false, letting the spatial navigation manager take care of the event in order to perform navigation. In case the method returns + * true, the {@link #keyWasPressed} method is called to let the controller provide its own custom key event handling. + * + * @param {int} key The identifier for the key that was pressed. + * @returns {bool} Whether the controller wants to provide its own custom key event handling. + */ +TKController.prototype.wantsToHandleKey = function (key) { + return (this.scrollableElement !== null && (key == KEYBOARD_UP || key == KEYBOARD_DOWN)); +}; + +/** + * Triggered when a key was pressed and the receiver has expressed explicit interest in providing custom key event handling by returning true in + * the {@link #wantsToHandleKey} method. + * + * @param {int} key The identifier for the key that was pressed. + */ +TKController.prototype.keyWasPressed = function (key) { + // up should scroll + if (key == KEYBOARD_UP) { + this.scrollUp(); + } + // down should scroll + else if (key == KEYBOARD_DOWN) { + this.scrollDown(); + } + // done, play the sound + TKUtils.playSound(TKSpatialNavigationManager.soundToPlay); +}; + +/* ==================== Archival ==================== */ + +/** + * Called when the booklet's state is being archived. This method needs to return a list of properties reflecting the current state for the receiver. + * + * @returns {Object} The list of properties to archive as a hash-like object. + * @private + */ +TKController.prototype.archive = function () { + var archive = { + id: this.id + }; + // see if we can add a highlighted element index + if (this.highlightedElement !== null) { + archive.highlightedElementIndex = this.navigableElements.indexOf(this.highlightedElement); + } + // + return archive; +}; + +TKClass(TKController); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/* ==================== TKSpatialNavigationManager ==================== */ + +/** + * Indicates whether the spatial navigation manager is enabled, which currently is only the case on Apple TV, or within Safari for development purposes. + * @constant + * @type bool + */ +const TKSpatialNavigationManagerEnabled = (window.iTunes === undefined || window.iTunes.platform == 'AppleTV') ? true : (parseInt(window.iTunes.version, 0) < 9); + +/** + * The CSS class name applied to an element when it is highlighted by the spatial navigation manager. + * @constant + * @type String + */ +const TKSpatialNavigationManagerHighlightCSSClass = 'tk-highlighted'; +/** + * The CSS class name an element should have in order to be ignored by the spatial navigation manager. + * @constant + * @type String + */ +const TKSpatialNavigationManagerInactiveCSSClass = 'tk-inactive'; + +/** + * The up direction. + * @constant + * @type int + */ +const TKSpatialNavigationManagerDirectionUp = KEYBOARD_UP; +/** + * The right direction. + * @constant + * @type int + */ +const TKSpatialNavigationManagerDirectionRight = KEYBOARD_RIGHT; +/** + * The down direction. + * @constant + * @type int + */ +const TKSpatialNavigationManagerDirectionDown = KEYBOARD_DOWN; +/** + * The left direction. + * @constant + * @type int + */ +const TKSpatialNavigationManagerDirectionLeft = KEYBOARD_LEFT; +/** + * The list of keys the spatial navigation manager knows how to handle. + * @constant + * @type int + * @private + */ +const TKSpatialNavigationManagerKnownKeys = [KEYBOARD_UP, KEYBOARD_RIGHT, KEYBOARD_DOWN, KEYBOARD_LEFT, KEYBOARD_BACKSPACE, KEYBOARD_RETURN]; + +/** + * The number of controllers that are currently busy, when for instance performing a transition that should not be interrupted. When this variable is more than + * 0, key handling by the spatial navigation manager is suspended. + * @type int + */ +TKSpatialNavigationManager.busyControllers = 0; +/** + * The identifier for the sound to play for the current event loop. + * @type int + */ +TKSpatialNavigationManager.soundToPlay = null; + +/* ==================== Creating the shared instance lazily ==================== */ + +/** + * @name TKSpatialNavigationManager + * @property {TKSpatialNavigationManager} sharedManager The shared instance of the spatial navigation manager. TuneKit automatically creates a single instance + * of the {@link TKSpatialNavigationManager} class as needed, and developers should never have to create an instance themselves, instead using this property + * to retrieve the shared instance. + */ +TKSpatialNavigationManager._sharedManager = null; +TKSpatialNavigationManager.__defineGetter__('sharedManager', function () { + if (this._sharedManager === null) { + this._sharedManager = new TKSpatialNavigationManager(); + } + return this._sharedManager; +}); + +/* ==================== Constructor ==================== */ + +TKSpatialNavigationManager.inherits = TKObject; +TKSpatialNavigationManager.includes = [TKEventTriage]; +TKSpatialNavigationManager.synthetizes = ['managedController']; + +/** + * @class + * + *

The spatial navigation manager is a special controller type that sits behind the scenes and handles much of the keyboard interaction in order + * to provide navigation between navigable elements of the {@link #managedController}. By default, navigation between navigable elements is automatic and + * performed based on the location and metrics of each elements. The elements' metrics are those set by CSS and a controller is free to provide custom + * metrics for elements as it sees fit by implementing the {@link TKController#customMetricsForElement} method. Additionally, the automatic navigation + * can be completely bypassed should the managed controller provide a custom element to navigate to with the + * {@link TKController#preferredElementToHighlightInDirection} method.

+ * + * @extends TKObject + * @since TuneKit 1.0 + */ +function TKSpatialNavigationManager () { + this.callSuper(); + // + this._managedController = null; + /** + * The complete list of all elements that can be navigated to within this controller and all of its sub-controllers. + * @type Array + */ + this.navigableElements = []; + this.highlightedElement = null; + this.previousNavigation = null; + // register for keyboard events if we're running outside of the iTunes app + if (TKSpatialNavigationManagerEnabled) { + window.addEventListener('keydown', this, true); + } +}; + +/** + * @name TKSpatialNavigationManager.prototype + * @property managedController The managed controller is the controller that the spatial navigation manager queries for navigable elements + * and any customization of the otherwise automated navigation. Developers should not assign this property directly as the navigation controller takes care of + * that as the user navigates through controllers. + * @type TKController + */ +TKSpatialNavigationManager.prototype.setManagedController = function (controller) { + this._managedController = controller; + this.navigableElements = controller.navigableElements; + this.previousNavigation = null; + // is this the first time we're managing this controller? + if (controller._wasAlreadyManagedBySpatialNavigationManager === undefined) { + // see if it had an archived highlighted element + var archived_index = controller.getArchivedProperty('highlightedElementIndex'); + if (archived_index !== undefined) { + var archived_element = controller.navigableElements[archived_index]; + if (archived_element instanceof Element) { + controller.highlightedElement = archived_element; + } + } + // track that we've managed it before + controller._wasAlreadyManagedBySpatialNavigationManager = true; + } + // reset the highlighted element to be nothing + this.highlightedElement = null; + // if we have a preferred or recorded highlighted element, highlight that + if (controller.highlightedElement !== null) { + this.highlightElement(controller.highlightedElement); + } + // otherwise default to the top-most element + else { + this.highlightTopElement(); + } +}; + +TKSpatialNavigationManager.prototype.registerController = function (controller) { + var elements = controller.navigableElements; + for (var i = 0; i < elements.length; i++) { + this.addNavigableElement(elements[i]); + } +}; + +TKSpatialNavigationManager.prototype.unregisterController = function (controller) { + var elements = controller.navigableElements; + for (var i = 0; i < elements.length; i++) { + this.removeNavigableElement(elements[i]); + } +}; + +TKSpatialNavigationManager.prototype.addNavigableElement = function (element) { + // nothing to do if the new element is not rooted in the managed hierarchy or we already know it + if (!element._controller.isDescendentOfController(this._managedController) || + this.navigableElements.indexOf(element) > -1) { + return; + } + // and keep track of it + this.navigableElements.push(element); +}; + +TKSpatialNavigationManager.prototype.removeNavigableElement = function (element) { + // find the index for this element + var index = this.navigableElements.indexOf(element); + if (index < 0) { + return; + } + // remove elements from the tracking arrays + this.navigableElements.splice(index, 1); +}; + +/* ==================== Keyboard Navigation ==================== */ + +TKSpatialNavigationManager.prototype.handleKeydown = function (event) { + + var key = event.keyCode; + + // check if our controller knows what it's doing and let it take over in case it does + if (this._managedController.wantsToHandleKey(key)) { + // prevent default actions + event.stopPropagation(); + event.preventDefault(); + // have the controller do what it think is best in this case + this._managedController.keyWasPressed(key); + return; + } + + // reset the sound + TKSpatialNavigationManager.soundToPlay = null; + + // check we know about this key, otherwise, do nothing + if (TKSpatialNavigationManagerKnownKeys.indexOf(key) == -1) { + return; + } + + var navigation = TKNavigationController.sharedNavigation; + // first, check if we're hitting the back button on the home screen, in which case + // we don't want to do anything and let the User Agent do what's right to exit + if (event.keyCode == KEYBOARD_BACKSPACE && navigation.topController === homeController) { + return; + } + + // before we go any further, prevent the default action from happening + event.stopPropagation(); + event.preventDefault(); + + // check if we're busy doing other things + if (TKSpatialNavigationManager.busyControllers > 0) { + return; + } + // see if we pressed esc. so we can pop to previous controller + if (event.keyCode == KEYBOARD_BACKSPACE) { + var top_controller = navigation.topController; + if (top_controller !== homeController) { + // at any rate, play the exit sound + TKUtils.playSound(SOUND_EXIT); + // see if the top controller has a custom place to navigate to with the back button + if (top_controller.backButton instanceof Element && top_controller.backButton._navigationData !== undefined) { + navigation.pushController(TKController.resolveController(top_controller.backButton._navigationData.controller)); + } + // otherwise, just pop the controller + else { + navigation.popController(); + } + } + } + // check if we want to activate an element + else if (key == KEYBOARD_RETURN) { + if (this.highlightedElement !== null) { + var success = this.highlightedElement._controller.elementWasActivated(this.highlightedElement); + TKUtils.playSound(TKSpatialNavigationManager.soundToPlay === null ? SOUND_ACTIVATED : TKSpatialNavigationManager.soundToPlay); + } + else { + TKUtils.playSound(SOUND_LIMIT); + } + } + // keyboard nav + else { + var key_index = TKSpatialNavigationManagerKnownKeys.indexOf(key); + // do nothing if we don't have any highlightable elements or don't know about this navigation direction + if (this.navigableElements.length == 0 || key_index == -1) { + TKUtils.playSound(SOUND_LIMIT); + return; + } + // figure the index of the element to highlight + var index = this.nearestElementIndexInDirection(key); + + // get a pointer to the controller of the previous item if we have one + if (this.highlightedElement !== null) { + var previous_controller = this.highlightedElement._controller; + + // see if we're being provided custom navigation by the controller instance + var provided_preferred_element = false; + var preferred_highlighted_element = previous_controller.preferredElementToHighlightInDirection(this.highlightedElement, key); + // try again with the private method meant to be implemented by the sub-class + if (preferred_highlighted_element === undefined) { + preferred_highlighted_element = previous_controller._preferredElementToHighlightInDirection(this.highlightedElement, key); + } + // we explicitly do not want to highlight anything + if (preferred_highlighted_element === null) { + index = -1; + } + else if (preferred_highlighted_element !== undefined) { + var preferred_highlight_index = this.navigableElements.indexOf(preferred_highlighted_element); + // if this element is in our navigation list and is ready to be navigated to + if (preferred_highlight_index >= 0 && this.isElementAtIndexNavigable(preferred_highlight_index)) { + index = preferred_highlight_index; + provided_preferred_element = true; + } + } + + // stop right there if we have no useful index + if (index == -1) { + TKUtils.playSound(SOUND_LIMIT); + return; + } + } + + // get a pointer to the controller of the item we consider highlighting now + var next_controller = this.navigableElements[index]._controller; + + // we're moving out of a tab controller into one controller managed by that tab controller + // in which case we want to highlight the first item in that controller based on its orientation + if (previous_controller instanceof TKTabController && + this.highlightedElement._tabIndex !== undefined && + next_controller.parentController === previous_controller) { + index = this.navigableElements.indexOf(next_controller.highlightedElement || next_controller.navigableElements[0]); + } + // we're moving back to a tab element from an element managed by a controller + // that is itself managed by the very tab controller we're focusing, so let's highlight + // the element that is selected in that tab controller + else if (next_controller instanceof TKTabController && + this.navigableElements[index]._tabIndex !== undefined && + previous_controller.parentController === next_controller) { + index = this.navigableElements.indexOf(next_controller.tabs[next_controller.selectedIndex]); + } + // check if we were doing the reverse operation to the last one + else if (!provided_preferred_element && this.previousNavigation !== null && key_index == (this.previousNavigation.keyIndex + 2) % 4) { + var previous_element_index = this.navigableElements.indexOf(this.previousNavigation.element); + if (previous_element_index > -1 && this.isElementAtIndexNavigable(previous_element_index)) { + index = previous_element_index; + } + } + + // get a pointer to the next element to highlight + var next_highlighted_element = (index >= 0 && index < this.navigableElements.length) ? this.navigableElements[index] : null; + + // only highlight if we know what element to highlight + if (next_highlighted_element !== null && next_highlighted_element.isNavigable()) { + // track the interaction so we can go back to it + if (this.highlightedElement !== null) { + this.previousNavigation = { + element: this.highlightedElement, + keyIndex : key_index + }; + } + this.highlightElement(next_highlighted_element); + TKUtils.playSound(SOUND_MOVED); + } + else { + TKUtils.playSound(SOUND_LIMIT); + } + } +}; + +TKSpatialNavigationManager.prototype.nearestElementIndexInDirection = function (direction) { + // nothing to do if we don't have a next element + if (this.highlightedElement === null) { + if (direction == TKSpatialNavigationManagerDirectionUp) { + return this.bottomMostIndex(); + } + else if (direction == TKSpatialNavigationManagerDirectionRight) { + return this.leftMostIndex(); + } + else if (direction == TKSpatialNavigationManagerDirectionDown) { + return this.topMostIndex(); + } + else if (direction == TKSpatialNavigationManagerDirectionLeft) { + return this.rightMostIndex(); + } + } + // figure out parameters + var ref_position, target_edge; + if (direction == TKSpatialNavigationManagerDirectionUp) { + ref_position = TKRectMiddleOfTopEdge; + target_edge = TKRectBottomEdge; + } + else if (direction == TKSpatialNavigationManagerDirectionRight) { + ref_position = TKRectMiddleOfRightEdge; + target_edge = TKRectLeftEdge; + } + else if (direction == TKSpatialNavigationManagerDirectionDown) { + ref_position = TKRectMiddleOfBottomEdge; + target_edge = TKRectTopEdge; + } + else if (direction == TKSpatialNavigationManagerDirectionLeft) { + ref_position = TKRectMiddleOfLeftEdge; + target_edge = TKRectRightEdge; + } + // look for the closest element now + var index = -1; + var min_d = 10000000; + var highlight_index = this.navigableElements.indexOf(this.highlightedElement); + var ref_metrics = this.metricsForElement(this.highlightedElement); + var ref_point = ref_metrics.pointAtPosition(ref_position); + var ref_center = ref_metrics.pointAtPosition(TKRectCenter); + for (var i = 0; i < this.navigableElements.length; i++) { + // see if we should skip this element + if (!this.isElementAtIndexNavigable(i)) { + continue; + } + var metrics = this.metricsForElement(this.navigableElements[i]); + // go to next item if it's not in the right direction or already has highlight + if ((direction == TKSpatialNavigationManagerDirectionUp && metrics.pointAtPosition(TKRectBottomLeftCorner).y > ref_center.y) || + (direction == TKSpatialNavigationManagerDirectionRight && metrics.pointAtPosition(TKRectTopLeftCorner).x < ref_center.x) || + (direction == TKSpatialNavigationManagerDirectionDown && metrics.pointAtPosition(TKRectTopLeftCorner).y < ref_center.y) || + (direction == TKSpatialNavigationManagerDirectionLeft && metrics.pointAtPosition(TKRectTopRightCorner).x > ref_center.x) || + i == highlight_index) { + continue; + } + var d = metrics.edge(target_edge).distanceToPoint(ref_point); + if (d < min_d) { + min_d = d; + index = i; + } + } + // return the index, if any + return index; +}; + +TKSpatialNavigationManager.prototype.topMostIndex = function () { + var index = 0; + var min_y = 10000; + for (var i = 0; i < this.navigableElements.length; i++) { + if (!this.isElementAtIndexNavigable(i)) { + continue; + } + var y = this.metricsForElementAtIndex(i).y; + if (y < min_y) { + min_y = y; + index = i; + } + } + return index; +}; + +TKSpatialNavigationManager.prototype.rightMostIndex = function () { + var index = 0; + var max_x = 0; + for (var i = 0; i < this.navigableElements.length; i++) { + if (!this.isElementAtIndexNavigable(i)) { + continue; + } + var x = this.metricsForElementAtIndex(i).pointAtPosition(TKRectTopRightCorner).x; + if (x > max_x) { + max_x = x; + index = i; + } + } + return index; +}; + +TKSpatialNavigationManager.prototype.bottomMostIndex = function () { + var index = 0; + var max_y = 0; + for (var i = 0; i < this.navigableElements.length; i++) { + if (!this.isElementAtIndexNavigable(i)) { + continue; + } + var y = this.metricsForElementAtIndex(i).pointAtPosition(TKRectBottomRightCorner).y; + if (y > max_y) { + max_y = y; + index = i; + } + } + return index; +}; + +TKSpatialNavigationManager.prototype.leftMostIndex = function () { + var index = 0; + var min_x = 10000; + for (var i = 0; i < this.navigableElements.length; i++) { + if (!this.isElementAtIndexNavigable(i)) { + continue; + } + var y = this.metricsForElementAtIndex(i).x; + if (y < min_x) { + min_x = y; + index = i; + } + } + return index; +}; + +TKSpatialNavigationManager.prototype.metricsForElement = function (element) { + return element._controller.customMetricsForElement(element) || element.getBounds(); +}; + +TKSpatialNavigationManager.prototype.metricsForElementAtIndex = function (index) { + return this.metricsForElement(this.navigableElements[index]); +}; + +/** + * Highlight the top-most element in the list of navigable elements. + */ +TKSpatialNavigationManager.prototype.highlightTopElement = function () { + // now see if we need to enforce some default element + if (this.navigableElements.length > 0) { + this.highlightElement(this.navigableElements[this.topMostIndex()]); + } +}; + +/** + * Indicates whether a given element is navigable at the provided index in the {@link #navigableElements} array. + * + * @param {Element} element The index for the element in the {@link #navigableElements} array. + * @returns {bool} Whether the element can be navigated to. + */ +TKSpatialNavigationManager.prototype.isElementAtIndexNavigable = function (index) { + return this.navigableElements[index].isNavigable(); +}; + +/* ==================== Highlight Management ==================== */ + +/** + * Highlights a given element if it's part of the {@link #navigableElements} array. When an element receives highlight, a highlight event is + * dispatched to that element, while an unhighlight event is dispatched to the element that previously had highlight. + * + * @param {Element} element The element to highlight. + */ +TKSpatialNavigationManager.prototype.highlightElement = function (element) { + // nothing to do if we don't really have an element to highlight + if (!(element instanceof Element)) { + return; + } + // check that this element is navigable, and do nothing if it's not + var navigation_index = this.navigableElements.indexOf(element); + if (navigation_index == -1 || !this.isElementAtIndexNavigable(navigation_index)) { + return; + } + // + if (this.highlightedElement !== null) { + this.highlightedElement.dispatchEvent(TKUtils.createEvent('unhighlight', element)); + if (TKSpatialNavigationManagerEnabled) { + this.highlightedElement.removeClassName(TKSpatialNavigationManagerHighlightCSSClass); + } + } + // + element.dispatchEvent(TKUtils.createEvent('highlight', this.highlightedElement)); + if (TKSpatialNavigationManagerEnabled) { + element.addClassName(TKSpatialNavigationManagerHighlightCSSClass); + } + this.highlightedElement = element; + // track on its controller that it was the last with highlight + element._controller.highlightedElement = element; +}; + +TKClass(TKSpatialNavigationManager); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/** + * @class + * @name TKNavigationControllerDelegate + * @since TuneKit 1.0 + */ + +/** + * Indicates that a new controller is becoming the top controller and is about to become visible on screen. + * + * @name navigationControllerWillShowController + * @function + * + * @param {TKNavigationController} navigationController The navigation controller. + * @param {TKController} controller The controller that is about to be shown by the navigation controller. + * @memberOf TKNavigationControllerDelegate.prototype + */ +const TKNavigationControllerWillShowController = 'navigationControllerWillShowController'; +/** + * Indicates that a new controller has become the top controller and is fully visible on screen. + * + * @name navigationControllerDidShowController + * @function + * + * @param {TKNavigationController} navigationController The navigation controller. + * @param {TKController} controller The controller that is has been shown by the navigation controller. + * @memberOf TKNavigationControllerDelegate.prototype + */ +const TKNavigationControllerDidShowController = 'navigationControllerDidShowController'; + +TKNavigationController.inherits = TKController; +TKNavigationController.synthetizes = ['topController']; + +/** + * @property {TKNavigationController} sharedNavigation The shared instance of the navigation controller. TuneKit automatically creates a single instance + * of the {@link TKNavigationController} class as needed, and developers should never have to create an instance themselves, instead using this property + * to retrieve the shared instance. + */ +TKNavigationController.sharedNavigation = null; + +/** + * @class + * + *

The spatial navigation manager is a pre-insantiated singleton controller that handles the logic for all navigation between controllers. The currently + * showing controller is the {@link #topController}, and is the last item of the {@link #controllers} array, which traces the complete navigation history + * from the home controller onwards. By implementing the {@link TKNavigationControllerDelegate} protocol, the navigation controller's {@link #delegate} can + * track as the user navigates between controllers. While the {@link TKController#navigatesTo} property should be sufficient to alloe developers to specify + * what action triggers a navigation to a given controller, the {@link #pushController} and {@link #popController} methods also allow a programmatic + * interaction with the navigation controller.

+ * + * @extends TKController + * @since TuneKit 1.0 + * + * @param {Object} data A hash of properties to use as this object is initialized. + */ +function TKNavigationController (data) { + /** + * The list of controllers in the navigation stack. The controller at the first index is the root-most controller, while the controller at the last index is + * the top controller. + * @type Array + */ + this.controllers = []; + /** + * The delegate for this navigation controller, an object implementing the {@link TKNavigationControllerDelegate} protocol. + * @type Object + */ + this.delegate = data.delegate || null; + this.rootController = data.rootController || null; + this.previousController = null; + // + this.busy = false; + // + this.callSuper(data); + // see if we have a stack to restore + if (bookletController.archive !== undefined) { + var stack = bookletController.archive.navigationStack; + var restored_controllers = []; + for (var i = 0; i < stack.length; i++) { + var controller = TKController.controllers[stack[i]]; + restored_controllers.push(controller); + controller.loadView(); + } + // push the last controller + this.pushController(restored_controllers[restored_controllers.length - 1]); + // and fake the controllers stack + this.controllers = restored_controllers; + } + // see if we have a root set up + else if (this.rootController !== null) { + this.pushController(this.rootController); + } + // + TKNavigationController.sharedNavigation = this; +}; + +/* ==================== Controllers ==================== */ + +/** + * @name TKNavigationController.prototype + * @property {TKController} topController The controller at the top of the navigation stack of {@link #controllers}. + */ +TKNavigationController.prototype.getTopController = function () { + return (this.controllers.length > 0) ? this.controllers[this.controllers.length - 1] : null; +}; + +/** + * Pushes a new controller to the top of the navigation stack, triggering an animated transition of the new top controller using its + * {@link TKController.becomesActiveTransition} property and the {@link TKController.becomesInactiveTransition} property of the previous {@link #topController} + * @param {TKController} controller The controller to push onto the navigation stack. + */ +TKNavigationController.prototype.pushController = function (controller) { + // do nothing if we're busy + if (this.busy) { + return; + } + // + TKTransaction.begin(); + // get pointers to object we'll manipulate + var previous_controller = this.topController; + var next_view = controller.view; + // fire delegate saying we're moving to a new controller + if (TKUtils.objectHasMethod(this.delegate, TKNavigationControllerWillShowController)) { + this.delegate[TKNavigationControllerWillShowController](this, controller); + } + // put the controller in our array + this.controllers.push(controller); + // notify of upcoming change + if (previous_controller !== null) { + previous_controller._viewWillDisappear(); + previous_controller.viewWillDisappear(); + } + controller._viewWillAppear(); + controller.viewWillAppear(); + // add it to the tree + this.view.appendChild(controller.view); + // + if (previous_controller !== null) { + this.transitionToController(previous_controller, controller); + } + else { + this.busy = true; + this.transitionDidComplete(); + TKSpatialNavigationManager.sharedManager.managedController = controller; + } + // + TKTransaction.commit(); +}; + +/** + * Pops the top {@link #topController} off the navigation stack, triggering an animated transition of the new top controller using its + * {@link TKController.becomesActiveTransition} property and the {@link TKController.becomesInactiveTransition} property of the previous {@link #topController} + */ +TKNavigationController.prototype.popController = function () { + // do nothing if we're busy or if there's nothing to pop + if (this.busy || this.controllers.length < 2) { + return; + } + TKTransaction.begin(); + // fire delegate saying we're moving to a new controller + if (TKUtils.objectHasMethod(this.delegate, TKNavigationControllerWillShowController)) { + this.delegate[TKNavigationControllerWillShowController](this, this.controllers[this.controllers.length - 2]); + } + // update stack + var previous_controller = this.controllers.pop(); + var top_controller = this.topController; + // notify of upcoming change + previous_controller._viewWillDisappear(); + previous_controller.viewWillDisappear(); + top_controller._viewWillAppear(); + top_controller.viewWillAppear(); + // add it to the tree + this.view.appendChild(top_controller.view); + // transition + this.transitionToController(previous_controller, top_controller); + // + TKTransaction.commit(); +}; + +/* ==================== Transition ==================== */ + +TKNavigationController.prototype.transitionToController = function (previous_controller, top_controller) { + // mark that a transition is now in progress + this.busy = true; + // record some parameters that we will need at the end of the transition + this.previousController = previous_controller; + // figure out transitions + if (previous_controller !== null) { + if (IS_APPLE_TV && !previous_controller.enforcesCustomTransitions) { + previous_controller.becomesInactiveTransition = TKViewTransitionDissolveOut; + } + previous_controller.view.applyTransition(previous_controller.becomesInactiveTransition, false); + } + if (IS_APPLE_TV && !top_controller.enforcesCustomTransitions) { + top_controller.becomesActiveTransition = TKViewTransitionDissolveIn; + } + var top_controller_transition = top_controller.becomesActiveTransition; + top_controller_transition.delegate = this; + top_controller.view.applyTransition(top_controller_transition, false); + // + TKSpatialNavigationManager.sharedManager.managedController = top_controller; + // track that we're moving from screen to screen + window.dispatchEvent(TKUtils.createEvent('cursorwait', null)); +}; + +TKNavigationController.prototype.transitionDidComplete = function (transition) { + if (!this.busy) { + return; + } + var top_controller = this.topController; + // remove the old screen + if (this.previousController !== null) { + this.view.removeChild(this.previousController.view); + this.previousController._viewDidDisappear(); + this.previousController.viewDidDisappear(); + } + // notify of completed change + top_controller._viewDidAppear(); + top_controller.viewDidAppear(); + // fire delegate saying we've moved to a new controller + if (TKUtils.objectHasMethod(this.delegate, TKNavigationControllerDidShowController)) { + this.delegate[TKNavigationControllerDidShowController](this, top_controller); + } + // + this.busy = false; + // pre-load screens that we can navigate to from here + // for (var i = 0; i < top_controller.navigatesTo.length; i++) { + // var navigation_data = top_controller.navigatesTo[i]; + // // pointer to the controller + // var controller = navigation_data.controller; + // // if it's a string, try to find it in the controllers hash + // if (TKUtils.objectIsString(controller)) { + // controller = TKController.controllers[controller]; + // } + // // skip if we have an undefined object + // if (controller === undefined) { + // continue; + // } + // // otherwise, load it if it's not been loaded before + // if (controller._view === null) { + // controller.loadView(); + // } + // } + // done moving from screen to screen + window.dispatchEvent(TKUtils.createEvent('cursornormal', null)); +}; + +TKClass(TKNavigationController); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +const TKPageSliderControllerContainerCSSClass = 'tk-page-slider-controller-view'; + +TKPageSliderController.inherits = TKController; +TKPageSliderController.synthetizes = ['slidingViewData', 'pageControlData', 'previousPageButton', 'nextPageButton', 'highlightedPageIndex']; + +/** + * @class + * + *

A page slider controller adds the ability to browse through a collection of elements, often images, with nice and smooth transitions + * set up in CSS. Using this controller type, you can easily track when a new page is highlighted or activated. Optionally, you can also + * set up a series of indicators giving the user an overview of the number of images and arrows to navigate through elements, the connection + * between the various components being automatically handled behind the scenes for you.

+ * + * @extends TKController + * @since TuneKit 1.0 + * + * @param {Object} data A hash of properties to use as this object is initialized. + */ +function TKPageSliderController (data) { + this._previousPageButton = null; + this._nextPageButton = null; + /** + * Indicates whether the pages managed by the controller are navigable with keys. Defaults to true. + * @type bool + */ + this.highlightsFocusedPage = true; + /** + * Indicates whether navigation of pages is done strictly with paging buttons. Defaults to false, allowing the Apple remote to + * be used to navigate between pages. + * @type bool + */ + this.navigatesWithPagingButtonsOnly = false; + /** + * Indicates whether the focused page can get activated. Defaults to true, setting this to false plays the limit sound when + * the user attempts to activate the focused page. + * @type bool + */ + this.activatesFocusedPage = true; + /** + * Provides the list of directions that the user can navigate out of the list of pages. By default, this array is empty, meaning that if the + * {@link #navigatesWithPagingButtonsOnly} property is set to false and pages can be navigated with arrow keys, then the user will not + * be able to move focus out of the pages from either ends. The directions allowed are the TKSpatialNavigationManagerDirection family + * of constants. + * @type Array + */ + this.allowedOutwardNavigationDirections = []; + // set up the sliding view + /** + * The backing sliding view hosting the pages. + * @type TKSlidingView + * @private + */ + this.slidingView = new TKSlidingView(); + this.slidingView.ready = false; + this.slidingView.delegate = this; + // set up the page control + /** + * The backing page control hosting the page indicators. + * @type TKPageControl + * @private + */ + this.pageControl = new TKPageControl(); + this.pageControl.delegate = this; + // + this._slidingViewData = null; + this._pageControlData = null; + // + this.callSuper(data); +}; + +TKPageSliderController.prototype.processView = function () { + this.callSuper(); + // restore properties that have not been set yet since construction + this.restoreProperty('previousPageButton'); + this.restoreProperty('nextPageButton'); + this.restoreProperty('slidingViewData'); + this.restoreProperty('pageControlData'); + this.restoreProperty('highlightedPageIndex'); + // wire up actions if we have a previous and next button wired + // add the sliding view and page control containers + this.container = this._view.appendChild(document.createElement('div')); + this.container.addClassName(TKPageSliderControllerContainerCSSClass); + this.container.appendChild(this.slidingView.element); + this.container.appendChild(this.pageControl.element); + // ensure our first page gets told about its being highlighted + this.pageWasHighlighted(this.highlightedPageIndex); + this.syncPageButtons(); + // highlight the first page in case we have no explicit highlighted element + if ((this.highlightedElement === null || !this.highlightedElement.isNavigable()) && this.slidingView.ready && this.highlightsFocusedPage) { + this.highlightedElement = this.slidingView.activeElement; + } +}; + +/** + * @name TKPageSliderController.prototype + * @property {int} highlightedPageIndex The index of the page currently selected within the collection of pages. + */ +TKPageSliderController.prototype.getHighlightedPageIndex = function () { + return this.slidingView.activeElementIndex; +}; + +TKPageSliderController.prototype.setHighlightedPageIndex = function (index) { + if (index === null) { + return; + } + // apply to the sliding view if it's ready + if (this.slidingView.ready) { + this.slidingView.activeElementIndex = index; + if (this.highlightedElement.hasClassName(TKSlidingViewCSSElementClass)) { + this.registerNavigablePages(); + this.highlightedElement = this.slidingView.activeElement; + } + } +}; + +/** + * @name TKPageSliderController.prototype + * @property {String} previousPageButton A CSS selector matching a button to be used as the button to decrement the {@link #highlightedPageIndex}. + */ +TKPageSliderController.prototype.setPreviousPageButton = function (previousPageButton) { + if (previousPageButton === null) { + return; + } + // forget old button + if (this._previousPageButton) { + this.removeNavigableElement(this._previousPageButton); + } + // process new one + if (previousPageButton !== null) { + this._previousPageButton = this.view.querySelector(previousPageButton); + if (this._previousPageButton !== null) { + if (IS_APPLE_TV && !this.navigatesWithPagingButtonsOnly) { + this._previousPageButton.style.display = 'none'; + } + else { + this.addNavigableElement(this._previousPageButton); + } + } + } +}; + +/** + * @name TKPageSliderController.prototype + * @property {String} nextPageButton A CSS selector matching a button to be used as the button to increment the {@link #highlightedPageIndex}. + */ +TKPageSliderController.prototype.setNextPageButton = function (nextPageButton) { + if (nextPageButton === null) { + return; + } + // forget old button + if (this._nextPageButton) { + this.removeNavigableElement(this._nextPageButton); + } + // process new one + if (nextPageButton !== null) { + this._nextPageButton = this.view.querySelector(nextPageButton); + if (this._nextPageButton !== null) { + if (IS_APPLE_TV && !this.navigatesWithPagingButtonsOnly) { + this._nextPageButton.style.display = 'none'; + } + else { + this.addNavigableElement(this._nextPageButton); + } + } + } +}; + +/** + * @name TKPageSliderController.prototype + * @property {TKSlidingViewData} slidingViewData The set of properties used to set up the contents of the page slider. + */ +TKPageSliderController.prototype.setSlidingViewData = function (data) { + if (data === null) { + return; + } + // set up the data source if we have .elements on the data object + if (!TKUtils.objectIsUndefined(data.elements)) { + this.slidingView.dataSource = new TKSlidingViewDataSourceHelper(data.elements); + delete data.element; + } + // see if we have some intersting bits to pass through + var archived_page_index = this.getArchivedProperty('highlightedPageIndex'); + if (archived_page_index !== undefined) { + data.activeElementIndex = archived_page_index; + } + // copy properties + TKUtils.copyPropertiesFromSourceToTarget(data, this.slidingView); + // init our view + this.slidingView.init(); + // + this.slidingView.ready = true; + // + this.syncPageButtons(); + // add the currently focused element to the list of keyboard elements and highlight it + if (this.highlightsFocusedPage) { + this.registerNavigablePages(); + this.highlightedElement = this.slidingView.activeElement; + if (this.viewWasProcessed) { + TKSpatialNavigationManager.sharedManager.highlightElement(this.slidingView.activeElement); + } + } +}; + +/** + * @name TKPageSliderController.prototype + * @property {TKPageControlData} pageControlData The set of properties used to set up the contents of the optional page indicators. + */ +TKPageSliderController.prototype.setPageControlData = function (data) { + if (data === null) { + return; + } + // set up the data source + this.pageControl.dataSource = new TKPageControlDataSourceHelper(data); + // copy properties + TKUtils.copyPropertiesFromSourceToTarget(data, this.pageControl); + // init our control + this.pageControl.init(); + // get the current page from the sliding view if we have it set only after + if (this.slidingView.ready) { + this.pageControl.currentPage = this.highlightedPageIndex; + } +}; + +/* ==================== Event Handling ==================== */ + +// private method meant to be over-ridden by a controller sub-classes to provide a custom element +// to highlight, returning null means there's nothing custom to report +TKPageSliderController.prototype._preferredElementToHighlightInDirection = function (currentElement, direction) { + var can_exit_in_direction = (this.allowedOutwardNavigationDirections.indexOf(direction) != -1); + var element = this.callSuper(currentElement, direction); + if (!this.navigatesWithPagingButtonsOnly && currentElement.hasClassName(TKSlidingViewCSSElementClass)) { + if (direction == KEYBOARD_LEFT) { + if (this.slidingView.activeElementIndex <= 0 && !this.slidingView.loops) { + if (!can_exit_in_direction) { + element = null; + } + } + else { + element = this.slidingView.getElementAtIndex((this.slidingView.activeElementIndex + this.slidingView.numberOfElements - 1) % this.slidingView.numberOfElements); + } + } + else if (direction == KEYBOARD_RIGHT) { + if (this.slidingView.activeElementIndex >= this.slidingView.numberOfElements - 1 && !this.slidingView.loops) { + if (!can_exit_in_direction) { + element = null; + } + } + else { + element = this.slidingView.getElementAtIndex((this.slidingView.activeElementIndex + 1) % this.slidingView.numberOfElements); + } + } + } + return element; +}; + +TKPageSliderController.prototype.elementWasActivated = function (element) { + // previous page button pressed + if (element === this._previousPageButton) { + var can_navigate = (this.slidingView.activeElementIndex > 0 || this.slidingView.loops); + TKSpatialNavigationManager.soundToPlay = (can_navigate) ? SOUND_MOVED : SOUND_LIMIT; + if (can_navigate) { + this.unregisterNavigablePages(); + } + this.slidingView.activeElementIndex--; + } + // next page button pressed + else if (element === this._nextPageButton) { + var can_navigate = (this.slidingView.activeElementIndex < this.slidingView.numberOfElements - 1 || this.slidingView.loops); + TKSpatialNavigationManager.soundToPlay = (can_navigate) ? SOUND_MOVED : SOUND_LIMIT; + if (can_navigate) { + this.unregisterNavigablePages(); + } + this.slidingView.activeElementIndex++; + } + // focused element in the sliding view + else if (element.hasClassName(TKSlidingViewCSSFocusedClass)) { + if (this.activatesFocusedPage) { + this.pageWasSelected(this.slidingView.activeElementIndex); + } + else { + TKSpatialNavigationManager.soundToPlay = SOUND_LIMIT; + } + } + // fall back to default behavior + else { + this.callSuper(element); + } +}; + +TKPageSliderController.prototype.elementWasHighlighted = function (element, previouslyHighlightedElement) { + if (element.hasClassName(TKSlidingViewCSSElementClass)) { + this.slidingView.activeElementIndex = element._slidingViewIndex; + // track navigation on all elements if we're getting highlight for the first time + if (previouslyHighlightedElement !== null && + (!previouslyHighlightedElement.hasClassName(TKSlidingViewCSSElementClass) || + previouslyHighlightedElement._controller !== this)) { + this.registerNavigablePages(); + } + } +}; + +TKPageSliderController.prototype.elementWasUnhighlighted = function (element, nextHighlightedElement) { + // are we focusing an element outside of our sliding view? + if (element.hasClassName(TKSlidingViewCSSElementClass) && + (!nextHighlightedElement.hasClassName(TKSlidingViewCSSElementClass) || + nextHighlightedElement._controller !== this)) { + // make all the other elements non-navigable + this.unregisterNavigablePages(); + // save for the active one + this.addNavigableElement(this.slidingView.activeElement); + } +}; + +TKPageSliderController.prototype.syncPageButtons = function () { + // nothing to do if the sliding view is looping + if (this.slidingView.loops || !this.isViewLoaded()) { + return; + } + // check if the previous page button needs hiding + if (this._previousPageButton instanceof Element) { + this._previousPageButton[(this.slidingView.activeElementIndex <= 0 ? 'add' : 'remove') + 'ClassName']('inactive'); + } + // check if the next page button needs hiding + if (this._nextPageButton instanceof Element) { + this._nextPageButton[(this.slidingView.activeElementIndex >= this.slidingView.numberOfElements - 1 ? 'add' : 'remove') + 'ClassName']('inactive'); + } +}; + +TKPageSliderController.prototype.registerNavigablePages = function () { + if (this.navigatesWithPagingButtonsOnly) { + this.addNavigableElement(this.slidingView.activeElement); + } + else { + var elements = this.slidingView.element.querySelectorAll('.' + TKSlidingViewCSSElementClass); + for (var i = 0; i < elements.length; i++) { + this.addNavigableElement(elements[i]); + } + } +}; + +TKPageSliderController.prototype.unregisterNavigablePages = function () { + var elements = this.slidingView.element.querySelectorAll('.' + TKSlidingViewCSSElementClass); + for (var i = 0; i < elements.length; i++) { + this.removeNavigableElement(elements[i]); + } +}; + +/* ==================== TKSlidingView Protocol ==================== */ + +TKPageSliderController.prototype.slidingViewDidFocusElementAtIndex = function (view, index) { + if (this.highlightsFocusedPage && this.slidingView.ready) { + if (this.highlightedElement.hasClassName(TKSlidingViewCSSElementClass)) { + this.registerNavigablePages(); + } + else { + this.unregisterNavigablePages(); + this.addNavigableElement(this.slidingView.activeElement); + } + // make sure the element has focus + if (this.viewWasProcessed) { + TKSpatialNavigationManager.sharedManager.highlightElement(this.slidingView.activeElement); + } + } + // + this.pageControl.currentPage = index; + this.pageWasHighlighted(index); + // update the states of previous and next buttons + this.syncPageButtons(); +}; + +TKPageSliderController.prototype.slidingViewDidBlurElementAtIndex = function (view, index) { + if (this.highlightsFocusedPage) { + this.unregisterNavigablePages(); + } +}; + +TKPageSliderController.prototype.slidingViewDidSelectActiveElement = function (view, index) { + this.pageWasSelected(index); +}; + +TKPageSliderController.prototype.slidingViewStyleForItemAtIndex = function (view, index) { + return this.styleForPageAtIndex(index); +}; + +TKPageSliderController.prototype.slidingViewDidHoverElementAtIndex = function (view, index) { + this.pageWasHovered(index); +}; + +TKPageSliderController.prototype.slidingViewDidUnhoverElementAtIndex = function (view, index) { + this.pageWasUnhovered(index); +}; + +/* ==================== Placeholder Methods ==================== */ + +/** + * Triggered as the {@link #highlightedPageIndex} property has changed when a new page became focused. + * + * @param {int} index The index of the newly focused page + */ +TKPageSliderController.prototype.pageWasHighlighted = function (index) {}; + +/** + * Triggered as the focused page was selected by the user, either from clicking on the page or using the play/pause remote key. + * + * @param {int} index The index of the activated page + */ +TKPageSliderController.prototype.pageWasSelected = function (index) {}; + +TKPageSliderController.prototype.pageWasHovered = function (index) {}; + +TKPageSliderController.prototype.pageWasUnhovered = function (index) {}; + +/** + * This method allows to provide custom style rules for a page programatically any time the {@link #highlightedPageIndex} property changes. The values in this + * array are expected to be individual two-value arrays, where the first index holds the CSS property name, and the second index its value. + * + * @param {Array} index The index of the page for which we are trying to obtain custom styles. + */ +TKPageSliderController.prototype.styleForPageAtIndex = function (index) { + return []; +}; + +/* ==================== TKPageControl Protocol ==================== */ + +TKPageSliderController.prototype.pageControlDidUpdateCurrentPage = function (control, newPageIndex) { + this.slidingView.activeElementIndex = newPageIndex; + this.pageControl.updateCurrentPageDisplay(); +}; + +/* ==================== Archival ==================== */ + +TKPageSliderController.prototype.archive = function () { + var archive = this.callSuper(); + archive.highlightedPageIndex = this.highlightedPageIndex; + return archive; +}; + +TKClass(TKPageSliderController); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +TKLyricsController.inherits = TKController; +TKLyricsController.synthetizes = ['currentSong', 'previousSongButton', 'nextSongButton']; + +/** + * @class + * + *

A lyrics controller is designed to make it easy to flip through a collection of lyrics. This controller type automatically wires the left and + * right keys to navigate between songs, and the author should leverage the {@link TKController#scrollableElement} property to identify the container + * for the scrolling lyrics region. Loading of new song content should be done using the {@link #songDidChange} method.

+ * + * @extends TKController + * @since TuneKit 1.0 + * + * @param {Object} data A hash of properties to use as this object is initialized. + */ +function TKLyricsController (data) { + /** + * The number of songs that the controller will be flipping through. + * @type int + */ + this.numberOfSongs = 0; + this.defaultToFirstSong = false; + this._currentSong = null; + this._previousSongButton = null; + this._nextSongButton = null; + // + this.callSuper(data); +}; + +/* ==================== View Processing ==================== */ + +TKLyricsController.prototype.processView = function () { + this.callSuper(); + // restore properties that have not been set yet since construction + this.restoreProperty('previousSongButton'); + this.restoreProperty('nextSongButton'); + this.restoreProperty('currentSong'); + // default to first song + if (this.defaultToFirstSong && this._currentSong === null) { + this.currentSong = 0; + } +}; + +/* ==================== Keyboard Navigation ==================== */ + +TKLyricsController.prototype.wantsToHandleKey = function (key) { + return (key == KEYBOARD_LEFT || key == KEYBOARD_RIGHT) ? true : this.callSuper(key); +}; + +TKLyricsController.prototype.keyWasPressed = function (key) { + // default action is move, so wire that up + TKSpatialNavigationManager.soundToPlay = SOUND_MOVED; + // left should go to the previous song + if (key == KEYBOARD_LEFT) { + this.goToPreviousSong(); + } + // right should go to the next song + else if (key == KEYBOARD_RIGHT) { + this.goToNextSong(); + } + // let the default behavior happen too + this.callSuper(key); +}; + +/* ==================== Previous / Next Buttons ==================== */ + +/** + * @name TKLyricsController.prototype + * @property {String} previousSongButton The CSS selector for the element acting as the trigger to navigate to the previous song. + */ +TKLyricsController.prototype.setPreviousSongButton = function (previousSongButton) { + if (previousSongButton === null || IS_APPLE_TV) { + return; + } + // forget old button + if (this._previousSongButton) { + this.removeNavigableElement(this._previousSongButton); + } + // process new one + if (previousSongButton !== null) { + this._previousSongButton = this.view.querySelector(previousSongButton); + if (this._previousSongButton !== null) { + this.addNavigableElement(this._previousSongButton); + } + } +}; + +/** + * @name TKLyricsController.prototype + * @property {String} nextSongButton The CSS selector for the element acting as the trigger to navigate to the next song. + */ +TKLyricsController.prototype.setNextSongButton = function (nextSongButton) { + if (nextSongButton === null || IS_APPLE_TV) { + return; + } + // forget old button + if (this._nextSongButton) { + this.removeNavigableElement(this._nextSongButton); + } + // process new one + if (nextSongButton !== null) { + this._nextSongButton = this.view.querySelector(nextSongButton); + if (this._nextSongButton !== null) { + this.addNavigableElement(this._nextSongButton); + } + } +}; + +TKLyricsController.prototype.elementWasActivated = function (element) { + // previous page button pressed + if (element === this._previousSongButton) { + this.goToPreviousSong(); + } + // next page button pressed + else if (element === this._nextSongButton) { + this.goToNextSong(); + } + // fall back to default behavior + else { + this.callSuper(element); + } +}; + +/* ==================== Page Navigation ==================== */ + +/** + * Shows the previous song. + */ +TKLyricsController.prototype.goToPreviousSong = function () { + this.currentSong = ((this._currentSong + this.numberOfSongs) - 1) % this.numberOfSongs; +}; + +/** + * Shows the next song. + */ +TKLyricsController.prototype.goToNextSong = function () { + this.currentSong = (this._currentSong + 1) % this.numberOfSongs; +}; + +/** + * @name TKLyricsController.prototype + * @property {int} currentSong The index of the current song. Whenever this value changes, the {@link #songDidChange} method is called. + */ +TKLyricsController.prototype.setCurrentSong = function (song) { + if (song === null || song < 0 || song >= this.numberOfSongs) { + return; + } + // track what song we're on + this._currentSong = song; + // let our instance know that we've moved to a new song + this.songDidChange(song); +}; + +/** + * Triggered when a new song is displayed by the controller. + */ +TKLyricsController.prototype.songDidChange = function (song) {}; + +/* ==================== Archival ==================== */ + +TKLyricsController.prototype.archive = function () { + var archive = this.callSuper(); + archive.currentSong = this.currentSong; + return archive; +}; + +TKClass(TKLyricsController); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +/** + * @class + * @name TKTabControllerDelegate + * @since TuneKit 1.0 + */ + +/** + * Indicates that a new controller is becoming the tab controller's selected controller and is about to become visible on screen. + * + * @name tabControllerWillShowController + * @function + * + * @param {TKTabController} tabController The tab controller. + * @param {TKController} controller The controller that is about to be shown by the tab controller. + * @memberOf TKTabControllerDelegate.prototype + */ +const TKTabControllerWillShowController = 'tabControllerWillShowController'; +/** + * Indicates that a new controller has become the tab controller's selected controller and is fully visible on screen. + * + * @name tabControllerDidShowController + * @function + * + * @param {TKTabController} tabController The tab controller. + * @param {TKController} controller The controller that is being shown by the tab controller. + * @memberOf TKTabControllerDelegate.prototype + */ +const TKTabControllerDidShowController = 'tabControllerDidShowController'; + +/** + * The CSS class name applied to an element acting as a tab once it is the selected tab. + * @constant + * @type String + */ +const TKTabControllerSelectedCSSClass = 'tk-tab-selected'; + +TKTabController.inherits = TKController; +TKTabController.synthetizes = ['selectedController', 'selectedIndex', 'tabsSelector']; + +/** + * @class + * + *

A tab controller allows to bind a series of elements within the view, the tabs, to display each a given controller, the tab controller only + * allowing a single tab to be selected at once. Tabs are specified using the {@link #tabsSelector} CSS selector, and a controller for each tab needs to be + * stored in the {@link #controllers} array. By implementing the {@link TKTabControllerDelegate} protocol, a tab controller's {@link #delegate} can track as + * the user navigates between tabs. At any given time, the {@link #selectedController} property allows to find out which of the controllers is currently + * selected.

+ * + * @extends TKController + * @since TuneKit 1.0 + * + * @param {Object} data A hash of properties to use as this object is initialized. + */ +function TKTabController (data) { + this._tabsSelector = null; + this._selectedController = null; + /** + * The controllers managed by this tab controller, ordered in the same way as the elements matched by {@link #tabsSelector} are. + * @type Array + */ + this.controllers = []; + this.tabs = []; + /** + * The delegate for this tab controller, an object implementing the {@link TKTabControllerDelegate} protocol. + * @type Object + */ + this.delegate = null; + this.previousController = null; + // + this.busy = false; + // + this.callSuper(data); +}; + +/* ==================== Additional View Processing ==================== */ + +TKTabController.prototype.processView = function () { + this.callSuper(); + // + this.host = this._view.appendChild(document.createElement('div')); + this.host.addClassName('tk-tab-contents'); + // restore properties that have not been set yet since construction + this.restoreProperty('tabsSelector'); + this.restoreProperty('selectedIndex'); +}; + +/* ==================== Synthetized Properties ==================== */ + +/** + * @name TKTabController.prototype + * @property {String} tabsSelector A CSS selector matching the elements within the controller's view that should act as triggers to display the matching + * controller in the {@link #controllers} array. + */ +TKTabController.prototype.setTabsSelector = function (tabsSelector) { + if (tabsSelector === null) { + return; + } + // forget the old tabs + for (var i = 0; i < this.tabs.length; i++) { + var element = this.tabs[i]; + element._tabIndex = undefined; + element._controller = undefined; + this.removeNavigableElement(element); + } + // get the new tabs + this._tabsSelector = tabsSelector; + this.tabs = this._view.querySelectorAll(this._tabsSelector); + // nothing to do if we don't have tabs + if (this.tabs.length < 1) { + return; + } + for (var i = 0; i < this.tabs.length; i++) { + var tab = this.tabs[i]; + tab._tabIndex = i; + tab._controller = this; + this.addNavigableElement(tab); + } + // reset to the first tab, unless we have an archived one + var archived_index = this.getArchivedProperty('selectedIndex'); + this.selectedIndex = (archived_index === undefined || archived_index < 0) ? 0 : archived_index; +}; + +/* ==================== Keyboard Handling ==================== */ + +TKTabController.prototype.getNavigableElements = function () { + return this._navigableElements.concat(this.selectedController.navigableElements); +}; + +TKTabController.prototype.handleEvent = function (event) { + this.callSuper(event); + // + if (event.currentTarget._tabIndex !== undefined) { + if (event.type == 'highlight') { + this.selectedIndex = event.currentTarget._tabIndex; + } + } +}; + +TKTabController.prototype.elementWasActivated = function (element) { + this.callSuper(element); + // tab was activated + if (element._tabIndex !== undefined) { + // highlight in case we weren't already + if (this.highlightedElement !== element) { + TKSpatialNavigationManager.sharedManager.highlightElement(element); + } + // notify we were activated + else { + this.tabAtIndexWasActivated(element._tabIndex); + } + } +}; + +/** + * Indicates that a new tab has been activated at the given index. + * + * @param {int} index The index for the tab that was just activated. + */ +TKTabController.prototype.tabAtIndexWasActivated = function (index) {}; + +/* ==================== Controllers ==================== */ + +/** + * @name TKTabController.prototype + * @property {int} selectedIndex The index of the selected tab. + */ +TKTabController.prototype.getSelectedIndex = function () { + return (this._selectedController === null) ? -1 : this.controllers.indexOf(this._selectedController); +}; + +TKTabController.prototype.setSelectedIndex = function (index) { + var selected_index = this.selectedIndex; + if (index !== selected_index && index >= 0 && index < this.controllers.length) { + // move to the new controller + this.selectedController = this.controllers[index]; + } +}; + +/** + * @name TKTabController.prototype + * @property {TKController} selectedController The selected controller. + */ +TKTabController.prototype.setSelectedController = function (controller) { + var selected_index = this.controllers.indexOf(controller); + // do nothing if we don't know about such a controller, or we're already on this controller + if (controller === this._selectedController || selected_index == -1) { + return; + } + // clean up before starting a new transition + if (this.busy) { + this.transitionDidComplete(null); + } + // + TKTransaction.begin(); + // mark that a transition is now in progress + this.busy = true; + // get pointers to object we'll manipulate + var previous_controller = this._selectedController; + var next_view = controller.view; + // fire delegate saying we're moving to a new controller + if (TKUtils.objectHasMethod(this.delegate, TKTabControllerWillShowController)) { + this.delegate[TKTabControllerWillShowController](this, controller); + } + // track this is our newly selected controller + this._selectedController = controller; + // notify of upcoming change and update tabs styling + if (previous_controller !== null) { + previous_controller._viewWillDisappear(); + previous_controller.viewWillDisappear(); + } + controller._viewWillAppear(); + controller.viewWillAppear(); + // add it to the tree + this.host.appendChild(controller.view); + // transition + var manager = TKSpatialNavigationManager.sharedManager; + if (previous_controller !== null) { + // unregister the old controller + previous_controller.parentController = null; + manager.unregisterController(previous_controller); + // remove the selected CSS class from the previous tab, if any + this.tabs[this.controllers.indexOf(previous_controller)].removeClassName(TKTabControllerSelectedCSSClass); + this.transitionToController(previous_controller, controller); + } + else { + this.busy = true; + this.transitionDidComplete(); + // highlight the element + if (this.highlightedElement === null) { + this.highlightedElement = this.tabs[this.selectedIndex] + } + } + // add the selected CSS class to the new controller's tab + this.tabs[selected_index].addClassName(TKTabControllerSelectedCSSClass) + // also ensure that element has highlight + manager.highlightElement(this.tabs[selected_index]); + // and that the new controller is registered for navigation + controller.parentController = this; + manager.registerController(controller); + // + TKTransaction.commit(); +}; + +/* ==================== Transition ==================== */ + +TKTabController.prototype.transitionToController = function (previous_controller, top_controller) { + // record some parameters that we will need at the end of the transition + this.previousController = previous_controller; + // figure out transitions + if (previous_controller !== null) { + previous_controller.view.applyTransition(previous_controller.becomesInactiveTransition, false); + } + var top_controller_transition = top_controller.becomesActiveTransition; + top_controller_transition.delegate = this; + top_controller.view.applyTransition(top_controller_transition, false); +}; + +TKTabController.prototype.transitionDidComplete = function (transition) { + // update the highlightable items and notify of completed change + if (this.previousController !== null) { + if (this.previousController.view.parentNode === this.host) { + this.host.removeChild(this.previousController.view); + } + this.previousController._viewDidDisappear(); + this.previousController.viewDidDisappear(); + } + this._selectedController._viewDidAppear(); + this._selectedController.viewDidAppear(); + // fire delegate saying we've moved to a new controller + if (TKUtils.objectHasMethod(this.delegate, TKTabControllerDidShowController)) { + this.delegate[TKTabControllerDidShowController](this, this._selectedController); + } + // not busy anymore + this.busy = false; +}; + +/* ==================== Archival ==================== */ + +TKTabController.prototype.archive = function () { + var archive = this.callSuper(); + archive.selectedIndex = this.selectedIndex; + return archive; +}; + +TKClass(TKTabController); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +const TKSlideshowControllerContainerCSSClass = 'tk-slideshow-controller-view'; + +TKSlideshowController.inherits = TKController; +TKSlideshowController.synthetizes = ['slidingViewData', 'togglePlaybackButton', 'playing', 'currentSlideIndex', 'numberOfSlides', 'previousSlideButton', 'nextSlideButton']; + +/** + * @class + * + *

A slideshow controller plays through a collection of slides, also allowing to control the playback state and position of the slideshow. Control + * buttons are easily wired and remote-based navigation is completely automated.

+ * + * @extends TKController + * @since TuneKit 1.0 + * + * @param {Object} data A hash of properties to use as this object is initialized. + */ +function TKSlideshowController (data) { + // public properties + this._slidingViewData = null; + this._togglePlaybackButton = null; + this._previousSlideButton = null; + this._nextSlideButton = null; + this._playing = null; + /** + * Indicates whether the slideshow loops through for constant playback. Defaults to true. + * @type bool + */ + this.loops = true; + /** + * Indicates the duration in milliseconds each slide remains on screen. + * @type int + */ + this.interval = 3000; + this.timer = null; + this.willNeedToResume = true; + // set up the sliding view + this.slidingView = new TKSlidingView(); + this.slidingView.ready = false; + this.slidingView.delegate = this; + // + this.callSuper(data); +}; + +/* ==================== View Processing ==================== */ + +TKSlideshowController.prototype.processView = function () { + this.callSuper(); + // restore properties that have not been set yet since construction + this.restoreProperty('slidingViewData'); + this.restoreProperty('previousSlideButton'); + this.restoreProperty('nextSlideButton'); + this.restoreProperty('togglePlaybackButton'); + this.restoreProperty('currentSlideIndex'); + this.restoreProperty('playing'); + // add the sliding view and slide control containers + this.container = this._view.appendChild(document.createElement('div')); + this.container.addClassName(TKSlideshowControllerContainerCSSClass); + this.container.appendChild(this.slidingView.element); + // ensure our first slide gets told about its being highlighted + this.slideDidChange(this.currentSlideIndex); + // start playing by default + if (this._playing === null) { + this.willNeedToResume = true; + } +}; + +TKSlideshowController.prototype._viewDidAppear = function () { + if (this.willNeedToResume) { + this.playing = true; + } +}; + +TKSlideshowController.prototype._viewWillDisappear = function () { + this.willNeedToResume = this.playing; + this.playing = false; +}; + +/* ==================== Synthetized Properties ==================== */ + +/** + * @name TKSlideshowController.prototype + * @property {bool} playing Indicates the current playback state of the slideshow, defaults to true. + */ +TKSlideshowController.prototype.setPlaying = function (playing) { + if (this._playing == playing) { + return; + } + // pause + if (!playing) { + window.clearTimeout(this.timer); + } + // resume + else { + this.rewindTimer(); + } + // remember ivar + this._playing = playing; + // inform the playback state changed + this.playbackStateDidChange(); +}; + +/** + * @name TKSlideshowController.prototype + * @property {int} numberOfSlides Indicates how many slides total are in the slideshow. + */ +TKSlideshowController.prototype.getNumberOfSlides = function () { + return (!this.slidingView.ready) ? 0 : this.slidingView.numberOfElements; +}; + +/** + * @name TKSlideshowController.prototype + * @property {int} currentSlideIndex Indicates the index of the current slide. + */ +TKSlideshowController.prototype.getCurrentSlideIndex = function () { + return this.slidingView.activeElementIndex; +}; + +TKSlideshowController.prototype.setCurrentSlideIndex = function (index) { + if (index === null || !this.slidingView.ready) { + return; + } + // out of range + if (index < 0 || index >= this.numberOfSlides) { + return; + } + // update the slideshow index + this.slidingView.activeElementIndex = index; + // update timers if we're running + if (this.playing) { + // cancel the previous timer in case we still had one running + window.clearTimeout(this.timer); + // rewind it, and set playback to false in case we can't rewind any further + if (!this.rewindTimer()) { + this.playing = false; + } + } +}; + +/** + * @name TKSlideshowController.prototype + * @property {String} togglePlaybackButton A CSS selector matching a button to be used as the button to control the playback state. + */ +TKSlideshowController.prototype.setTogglePlaybackButton = function (togglePlaybackButton) { + if (togglePlaybackButton === null) { + return; + } + // forget old button + if (this._togglePlaybackButton) { + this._togglePlaybackButton.removeEventListener('click', this, false); + } + // process new one + this._togglePlaybackButton = this.view.querySelector(togglePlaybackButton); + if (this._togglePlaybackButton !== null) { + if (IS_APPLE_TV) { + this._togglePlaybackButton.style.display = 'none'; + } + else { + this._togglePlaybackButton.addEventListener('click', this, false); + } + } +}; + +/** + * @name TKSlideshowController.prototype + * @property {String} previousSlideButton A CSS selector matching a button to be used as the button to decrement the {@link #currentSlideIndex}. + */ +TKSlideshowController.prototype.setPreviousSlideButton = function (previousSlideButton) { + if (previousSlideButton === null) { + return; + } + // forget old button + if (this._previousSlideButton) { + this._previousSlideButton.removeEventListener('click', this, false); + } + // process new one + this._previousSlideButton = this.view.querySelector(previousSlideButton); + if (this._previousSlideButton !== null) { + if (IS_APPLE_TV) { + this._previousSlideButton.style.display = 'none'; + } + else { + this._previousSlideButton.addEventListener('click', this, false); + } + } +}; + +/** + * @name TKSlideshowController.prototype + * @property {String} nextSlideButton A CSS selector matching a button to be used as the button to increment the {@link #currentSlideIndex}. + */ +TKSlideshowController.prototype.setNextSlideButton = function (nextSlideButton) { + if (nextSlideButton === null) { + return; + } + // forget old button + if (this._nextSlideButton) { + this._nextSlideButton.removeEventListener('click', this, false); + } + // process new one + this._nextSlideButton = this.view.querySelector(nextSlideButton); + if (this._nextSlideButton !== null) { + if (IS_APPLE_TV) { + this._nextSlideButton.style.display = 'none'; + } + else { + this._nextSlideButton.addEventListener('click', this, false); + } + } +}; + +/** + * @name TKSlideshowController.prototype + * @property {TKSlidingViewData} slidingViewData The set of properties used to set up the contents of the page slider. + */ +TKSlideshowController.prototype.setSlidingViewData = function (data) { + if (data === null) { + return; + } + // set up the data source if we have .elements on the data object + if (!TKUtils.objectIsUndefined(data.elements)) { + this.slidingView.dataSource = new TKSlidingViewDataSourceHelper(data.elements); + delete data.element; + } + // see if we have some intersting bits to pass through + var archived_slide_index = this.getArchivedProperty('currentSlideIndex'); + if (archived_slide_index !== undefined) { + data.activeElementIndex = archived_slide_index; + } + // copy properties + TKUtils.copyPropertiesFromSourceToTarget(data, this.slidingView); + // init our view + this.slidingView.init(); + // + this.slidingView.ready = true; +}; + +/* ==================== Previous / Next Slide ==================== */ + +TKSlideshowController.prototype.attemptToGoToPreviousSlide = function () { + if (!this.loops && this.currentSlideIndex <= 0) { + TKSpatialNavigationManager.soundToPlay = SOUND_LIMIT; + } + else { + this.goToPreviousSlide(); + } +}; + +TKSlideshowController.prototype.attemptToGoToNextSlide = function () { + if (!this.loops && this.currentSlideIndex >= this.numberOfSlides - 1) { + TKSpatialNavigationManager.soundToPlay = SOUND_LIMIT; + } + else { + this.goToNextSlide(); + } +}; + +TKSlideshowController.prototype.goToPreviousSlide = function () { + this.currentSlideIndex = ((this.currentSlideIndex + this.numberOfSlides) - 1) % this.numberOfSlides; +}; + +TKSlideshowController.prototype.goToNextSlide = function () { + this.currentSlideIndex = (this.currentSlideIndex + 1) % this.numberOfSlides; +}; + +TKSlideshowController.prototype.rewindTimer = function () { + if (this.loops || this.currentSlideIndex < this.numberOfSlides - 1) { + var _this = this; + this.timer = window.setTimeout(function () { + _this.goToNextSlide(); + }, this.interval); + return true; + } + else { + return false; + } +}; + +/* ==================== Keyboard Navigation ==================== */ + +TKSlideshowController.prototype.wantsToHandleKey = function (key) { + return (key == KEYBOARD_LEFT || key == KEYBOARD_RIGHT || key == KEYBOARD_RETURN) ? true : this.callSuper(key); +}; + +TKSlideshowController.prototype.keyWasPressed = function (key) { + // default action is move, so wire that up + TKSpatialNavigationManager.soundToPlay = SOUND_MOVED; + // left should go to the previous slide + if (key == KEYBOARD_LEFT) { + this.attemptToGoToPreviousSlide(); + } + // right should go to the next slide + else if (key == KEYBOARD_RIGHT) { + this.attemptToGoToNextSlide(); + } + // return key should toggle playback + else if (key == KEYBOARD_RETURN) { + TKSpatialNavigationManager.soundToPlay = SOUND_ACTIVATED; + this.playing = !this.playing; + } + // let the default behavior happen too + this.callSuper(key); +}; + +TKSlideshowController.prototype.elementWasActivated = function (element) { + // toggle playback button pressed + if (element === this._togglePlaybackButton) { + this.playing = !this.playing; + } + // previous slide button pressed + else if (element === this._previousSlideButton) { + this.attemptToGoToPreviousSlide(); + } + // next slide button pressed + else if (element === this._nextSlideButton) { + this.attemptToGoToNextSlide(); + } + // fall back to default behavior + else { + this.callSuper(element); + } +}; + +/* ==================== TKSlidingView Protocol ==================== */ + +TKSlideshowController.prototype.slidingViewDidFocusElementAtIndex = function (view, index) { + this.slideDidChange(index); +}; + +TKSlideshowController.prototype.slidingViewStyleForItemAtIndex = function (view, index) { + return this.styleForSlideAtIndex(index); +}; + +/* ==================== Placeholder Methods ==================== */ + +/** + * Triggered when the playback state has changed. + */ +TKSlideshowController.prototype.playbackStateDidChange = function () {}; + +/** + * Triggered when the {@link #currentSlideIndex} property has changed. + * + * @param {int} index The index of the current slide. + */ +TKSlideshowController.prototype.slideDidChange = function (index) {}; + +/** + * This method allows to provide custom style rules for a slide programatically any time the {@link #currentSlideIndex} property changes. The values in this + * array are expected to be individual two-value arrays, where the first index holds the CSS property name, and the second index its value. + * + * @param {Array} index The index of the slide for which we are trying to obtain custom styles. + */ +TKSlideshowController.prototype.styleForSlideAtIndex = function (index) { + return []; +}; + +/* ==================== Archival ==================== */ + +TKSlideshowController.prototype.archive = function () { + var archive = this.callSuper(); + archive.currentSlideIndex = this.currentSlideIndex; + return archive; +}; + +TKClass(TKSlideshowController); +/* + * Copyright © 2009 Apple Inc. All rights reserved. + */ + +// XXX: this should be set dynamically as needed +const ARCHIVES_AND_RESTORES = false; + +var bookletController = new TKObject(); + +bookletController.init = function () { + // stop current playback + window.iTunes.stop(); + + // set up audio loop + this.startAudioLoop(); + + // determine play position if this a movie + if (appData.feature.XID){ + appData.feature.trackObj = this.getTrack(appData.feature); + if (appData.feature.trackObj && appData.feature.trackObj.bookmark != 0){ + this.dispatchDisplayUpdates(); + } + } + + // add event listeners + window.addEventListener("play", this, false); + window.addEventListener("pause", this, false); + window.addEventListener("videoclosed", this, false); + window.addEventListener("unload", this, false); + + // check if we have an archive to restore from + this.restoreFromJSON(); + + // create our navigation controller and add the home controller as the root controller + this.navigation = new TKNavigationController({ + id : 'navigation', + rootController : homeController, + delegate : this + }); +}; + +bookletController.archiveToJSON = function () { + if (!ARCHIVES_AND_RESTORES) { + return; + } + // + var archive = { + controllers: {} + }; + // first, get the navigation stack of controllers + var controllers_stack_IDs = []; + for (var i = 0; i < this.navigation.controllers.length; i++) { + controllers_stack_IDs.push(this.navigation.controllers[i].id); + } + archive.navigationStack = controllers_stack_IDs; + // then archive all known controllers that aren't the navigation stack + for (var i in TKController.controllers) { + if (i == 'navigation') { + continue; + } + archive.controllers[i] = TKController.controllers[i].archive(); + } + // archive is complete, now save it to disk + window.localStorage.archive = JSON.stringify(archive); +}; + +bookletController.restoreFromJSON = function () { + if (!ARCHIVES_AND_RESTORES) { + return; + } + // check if we have an archive to restore from + var json_archive = window.localStorage.archive; + if (json_archive === undefined) { + return; + } + // parse the JSON archive into a JS object that we track at all times + this.archive = JSON.parse(json_archive); +}; + +bookletController.handleEvent = function(event) { + switch (event.type) { + case "play": + // video has started to play - stop the audio loop + this.stopAudioLoop(); + //this.dispatchDisplayUpdates(); + break; + case "pause": + // video has paused + //this.dispatchDisplayUpdates(); + break; + case "videoclosed": + // video has stopped - restart audio loop + this.startAudioLoop(); + this.dispatchDisplayUpdates(); + + // stub to check what chapter we are on for sticky chapters + debug(iTunes.currentChapter); + break; + case "unload": + // archive our state + this.archiveToJSON(); + break; + default: + debug("Unknown event type in bookletController : " + event.type); + } +}; + +bookletController.startAudioLoop = function() { + + // if the loop exists already, we're being asked to resume + // check if we're set to do so, and if not, exit without starting playback + if (this.audioLoop && appData.audioLoop && !appData.audioLoop.loop) { + this.audioLoop.pause(); + this.audioLoop.volume = 0; + return; + } + + // create the loop if it doesn't exist yet + if (appData.audioLoop && !this.audioLoop) { + this.audioLoop = new Audio(); + this.audioLoop.src = appData.audioLoop.src; + // make sure this background audio is never displayed + this.audioLoop.style.display = "none"; + // add it to the document so that iTunes will notice it is there + document.body.appendChild(this.audioLoop); + this.audioLoop.volume = 0; + } + + if (this.audioLoop) { + this.audioLoop.loop = appData.audioLoop.loop; + this.audioLoop.volume = Math.min(1, window.iTunes.volume); + this.audioLoop.play(); + } +}; + +bookletController.stopAudioLoop = function() { + if (this.audioLoop) { + this.audioLoop.pause(); + this.audioLoop.loop = false; + this.audioLoop.currentTime = 0; // reset to beginning + } +}; + +bookletController.playbackHasStarted = function (){ + return (this.trackBookmark(appData.feature) == 0) ? false : true; +} + +bookletController.play = function (trackObj) { + var track = this.getTrack(trackObj); + + if (track != null){ + iTunes.stop(); + track.play(); + } +}; + +bookletController.playFeature = function (){ + bookletController.play(appData.feature); +}; + +bookletController.resumeFeature = function(){ + bookletController.playFeature(); +}; + +bookletController.playChapter = function (index){ + iTunes.stop(); + if (appData.feature.trackObj != null){ + appData.feature.trackObj.play({startChapterIndex : index}); + } +}; + +bookletController.getChapter = function (){ + if (appData.feature.trackObj && appData.feature.trackObj.chapters){ + if ((iTunes.currentChapter == 0 && appData.feature.trackObj.bookmark != 0) || IS_APPLE_TV){ + var estimatedChapter = Math.floor((appData.feature.trackObj.bookmark / appData.feature.trackObj.duration) * appData.feature.trackObj.chapters.length); + var actualChapter = -1; + + if ((appData.feature.trackObj.chapters[estimatedChapter].startOffsetTime / 1000) == appData.feature.trackObj.bookmark){ + } else if ((appData.feature.trackObj.chapters[estimatedChapter].startOffsetTime / 1000) < appData.feature.trackObj.bookmark){ + while (estimatedChapter < appData.feature.trackObj.chapters.length && (appData.feature.trackObj.chapters[estimatedChapter].startOffsetTime / 1000) < appData.feature.trackObj.bookmark){ + estimatedChapter++; + } + } else if ((appData.feature.trackObj.chapters[estimatedChapter].startOffsetTime / 1000) > appData.feature.trackObj.bookmark){ + while (estimatedChapter >= 0 && (appData.feature.trackObj.chapters[estimatedChapter].startOffsetTime / 1000) > appData.feature.trackObj.bookmark){ + estimatedChapter--; + } + } + actualChapter = estimatedChapter; + debug("GET CHAPTER: estimating: " + actualChapter); + return actualChapter; + } else { + debug("GET CHAPTER: itunes query: " + iTunes.currentChapter); + return iTunes.currentChapter; + } + } else { + return -1; + } +} + +bookletController.buildPlaylist = function (tracks){ + var tracklistObj = iTunes.createTempPlaylist(); + var tracklist = []; + + for (var i = 0; i < tracks.length; i++){ + var track = this.getTrack(tracks[i]); + if (track != null){ + tracklist.push(track); + } + } + + tracklistObj.addTracks(tracklist); + debug("added " + tracklist.length + " of " + tracks.length + " tracks successfully."); + return tracklistObj; +}; + +bookletController.buildNonLibraryPlaylist = function (tracks){ + var tracklistObj = iTunes.createTempPlaylist(); + var tracklist = []; + + for (var i = 0; i < tracks.length; i++){ + var track = {}; + track.url = "videos/" + tracks[i].src; + track.title = tracks[i].string; + track.artist = appData.feature.artist; + track.album = appData.feature.title; + debug("adding: " + track.title + " (" + track.url + ")"); + tracklist.push(track); + } + + debug("pushing to tracklistOb"); + tracklistObj.addURLs(tracklist); + return tracklistObj; +}; + +bookletController.trackDuration = function (trackObj){ + var track = this.getTrack(trackObj); + if (track != null){ + debug("querying duration"); + return track.durationAsString; + } else { + return "0:00"; + } +}; + +bookletController.trackNumber = function (trackObj){ + var track = this.getTrack(trackObj); + if (track != null){ + debug("querying track number"); + return track.trackNumber; + } else { + return "0"; + } +}; + +bookletController.trackBookmark = function (trackObj){ + var track = this.getTrack(trackObj); + if (track != null){ + debug("querying bookmark"); + return track.bookmark; + } else { + return "0"; + } +}; + +bookletController.getTrack = function (trackObj){ + if (trackObj.XID){ + debug("searching by XID: " + trackObj.XID); + var iTunesTrack = window.iTunes.findTracksByXID(trackObj.XID); + if (iTunesTrack.length > 0){ + debug("found by XID"); + return iTunesTrack[0]; + } else { + debug("XID not found in library"); + return null; + } + } else { + debug("no XID"); + return null; + } +}; + +bookletController.playNonLibraryContent = function (trackObj){ + debug("videos/" + trackObj.src); + debug({title : trackObj.string, artist : appData.feature.artist, album : appData.feature.title}); + window.iTunes.play("videos/" + trackObj.src, {title : trackObj.string, artist : appData.feature.artist, album : appData.feature.title}); +}; + +bookletController.childControllers = []; + +bookletController.registerForDisplayUpdates = function (childController) { + if (this.childControllers.indexOf(childController) == -1) { + this.childControllers.push(childController); + } +}; + +bookletController.dispatchDisplayUpdates = function () { + for (var i=0; i < this.childControllers.length; i++) { + if (TKUtils.objectIsFunction(this.childControllers[i].updateDisplay)) { + this.childControllers[i].updateDisplay(); + } + } +}; + +/* ================= iTunes Emulation ======================== */ + +var iTunesEmulator = { + volume : 1, + platform : 'Emulator', + version : '-1' +}; + +iTunesEmulator.play = function (mediaLocation) { + debug("iTunesEmulator - play: " + mediaLocation); +}; + +iTunesEmulator.stop = function () { + debug("iTunesEmulator - stop"); +}; + +iTunesEmulator.findTracksByStoreID = function (storeID) { + debug("iTunesEmulator - findTracksByStoreID: " + storeID); + return [new ITunesTrackEmulator()]; +}; + +iTunesEmulator.findTracksByXID = function (xID) { + debug("iTunesEmulator - findTracksByXID: " + xID); + return [new ITunesTrackEmulator()]; +}; + +iTunesEmulator.createTempPlaylist = function () { + return { + tracks: [], + addTracks: function () {} + }; +}; + +function ITunesTrackEmulator() { +} + +ITunesTrackEmulator.prototype.play = function (params) { + debug("iTunesTrackEmulator - play: " + params); + // fake the play event to the window + var event = document.createEvent("HTMLEvents"); + event.initEvent("play", false, false); + window.dispatchEvent(event); + setTimeout(function() { + debug("iTunesTrackEmulator - coming back from playback"); + event = document.createEvent("HTMLEvents"); + event.initEvent("videoclosed", false, false); + window.dispatchEvent(event); + }, 5000); +}; + +/* ================= Initialisation ======================== */ + +window.addEventListener('load', function () { + // override select start + document.onselectstart = function() { return false; }; + // check for iTunes object, create a dummy if it doesn't exist + if (!window.iTunes) { + window.iTunes = iTunesEmulator; + } + // init the booklet controller + bookletController.init(); +}, false); diff --git a/compile.sh b/compile.sh new file mode 100644 index 0000000..f79ab19 --- /dev/null +++ b/compile.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +BABEL=./node_modules/babel-cli/bin/babel.js +SASS=./node_modules/node-sass/bin/node-sass +MUSTACHE=./node_modules/mustache/bin/mustache + +DATA_FILE=data.json + +SOURCE_ROOT=src +TARGET_DIR="iTunes Extras.ite" + +rm -r "${TARGET_DIR}" +mkdir -p "${TARGET_DIR}" + +cp -R TuneKit/ "${TARGET_DIR}/TuneKit/" + +for file in $(find ${SOURCE_ROOT} -type f) +do + echo -n "Compiling $file..." + dir=$(dirname "$file") + filename=$(basename "$file") + extension="${filename##*.}" + filename="${filename%.*}" + filename="${filename%.*}" # For double extensions + + if [[ $filename == _* ]]; then + echo -en "\033[0;33m" + echo " Skipping" + echo -en "\033[0;00m" + continue + fi + + targetDir="${TARGET_DIR}${dir#${SOURCE_ROOT}}" + partialTarget="${targetDir}/${filename}" + + mkdir -p "$targetDir" + + case "$file" in + *.xml.mustache ) + ${MUSTACHE} "${DATA_FILE}" "${file}" "${partialTarget}.xml" + ;; + *.plist.mustache ) + ${MUSTACHE} "${DATA_FILE}" "${file}" "${partialTarget}.plist" + ;; + *.js.mustache ) + ${MUSTACHE} "${DATA_FILE}" "${file}" | ${BABEL} --out-file "${partialTarget}.js" --presets env + ;; + *.js ) + ${BABEL} "${file}" --out-file "${partialTarget}.js" --presets env + ;; + *.scss ) + ${SASS} --no-cache --output-style compressed "$file" > "${partialTarget}.css" + ;; + *) + cp "$file" "${partialTarget}.${extension}" + ;; + esac + echo -en "\033[0;92m" + echo " Done" + echo -en "\033[0;00m" +done + +echo -n "Copying Assets... " +cp -R assets/ "${TARGET_DIR}/" +echo -en "\033[0;92m" +echo " Done" +echo -en "\033[0;00m" \ No newline at end of file diff --git a/data.json b/data.json new file mode 100644 index 0000000..65f0d2f --- /dev/null +++ b/data.json @@ -0,0 +1,76 @@ +{ + "XID": "TEST:uuid:5F861BFF-C205-4F6C-94F0-2FEEF662404D", + "movieID": 982749837, + "extrasID": 530706165, + "extrasVersion": "1.0", + "extrasBuildNumber": 42, + "meta": { + "title": "König Ödipus", + "artist": "Sven Schütze", + "description": "Mit nur neun Requisiten und rasanten Rollenwechseln erzählt Bodo Wartke die Geschichte des Ödipus, Sohn des Laios, König von Theben, der unwissend seinen eigenen Vater tötet. Und später, als Belohnung dafür, dass er Theben von der Sphinx befreit, Iokaste, die Witwe des Königs und damit seine eigene Mutter, zur Ehefrau erhält. Ein Solo-Theater mit dem Klavierkabarettisten in allen 14 Rollen! Bodo Wartkes exzellente Darbietung seiner Bühnenfassung der klassischen Tragödie „König Ödipus“ bietet einen barrierefreien Einstieg in einen zu Recht berühmten Sagenstoff und vereint Komödie und Tragödie zu einem fantastischen und unvergesslichen Theaterabend – so macht Bildung Spaß! (aus dem Pressetext).", + "longDescription": "Mit nur neun Requisiten und rasanten Rollenwechseln erzählt Bodo Wartke die Geschichte des Ödipus, Sohn des Laios, König von Theben, der unwissend seinen eigenen Vater tötet. Und später, als Belohnung dafür, dass er Theben von der Sphinx befreit, Iokaste, die Witwe des Königs und damit seine eigene Mutter, zur Ehefrau erhält. Ein Solo-Theater mit dem Klavierkabarettisten in allen 14 Rollen! Bodo Wartkes exzellente Darbietung seiner Bühnenfassung der klassischen Tragödie „König Ödipus“ bietet einen barrierefreien Einstieg in einen zu Recht berühmten Sagenstoff und vereint Komödie und Tragödie zu einem fantastischen und unvergesslichen Theaterabend – so macht Bildung Spaß! (aus dem Pressetext).", + "genre": "Comedy", + "releaseDate": "2010-04-11T00:00:00Z", + "year": "2010", + "studio": "ReimKultur", + "sort-name": "König Ödipus" + }, + "features": [ + { + "title": "Gespräch I", + "description": "Katrin Jäger spricht mit Bodo Wartke, Sven Schütze und Carmen Kalisch über die Entsehung von „König Ödipus“, die Adaptionsarbeit, die Proben, über dramaturgische und schauspielerische Herausforderungen.", + "src": "Gespraech_I.m4v", + "imageName": "Gespraech_I.png", + "duration": "43:03" + }, + { + "title": "Interview mit Polybos", + "description": "Katrin Jäger spricht mit Bodo Wartke über die Figur des Polybos.", + "src": "Interview_mit_Polybos.m4v", + "imageName": "Interview_mit_Polybos.png", + "duration": "0:50" + }, + { + "title": "Gespräch II", + "description": "Katrin Jäger spricht mit Bodo Wartke, Sven Schütze und Carmen Kalisch tiefergehend über die Problematik des Schicksalsbegriffs und den Umgang damit in Bodo Wartkes „König Ödipus“.", + "src": "Gespraech_II.m4v", + "imageName": "Gespraech_II.png", + "duration": "28:02" + }, + { + "title": "Gespräche III", + "description": "Carl der Löwe plaudert mit Katrin Jäger über seine langjährige Karriere im Showgeschäft und seine Rolle als Sphinx im „König Ödipus“.", + "src": "Gespraech_III.m4v", + "imageName": "Gespraech_III.png", + "duration": "07:02" + }, + { + "title": "Das Making-of", + "description": "Wie „König Ödipus“ auf die DVD kam.", + "src": "Making-of.m4v", + "imageName": "Making-of.png", + "duration": "43:10" + }, + { + "title": "Episode IV: Ödipus und Teiresias", + "description": "Die erste von Bodo verfasste Szene des Dramas, hier in der Fassung der DVD zu „Ich denke, also sing’ ich“, aufgezeichnet 2004 im Werk9 in Berlin.", + "src": "Episode_IV.m4v", + "imageName": "Episode_IV.png", + "duration": "9:41" + }, + { + "title": "Finale Mortale", + "description": "Anlässlich der gemeinsamen „United Slapstick Show“ erweiterte Bodo im Jahr 2000 das bis dahin als alleinstehende Zugabe existierende Ende des Stückes um etliche Rollen und Verse.", + "src": "Finale_Mortale.m4v", + "imageName": "Finale_Mortale.png", + "duration": "10:12" + }, + { + "title": "Antigone", + "description": "Das Sequel zu „König Ödipus“.", + "src": "Antigone.m4v", + "imageName": "Antigone.png", + "duration": "01:32" + } + ] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..0291835 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3246 @@ +{ + "name": "iTunes Extras Template", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", + "integrity": "sha1-0FVMIlZjbi9W58LlrRg/hZQo2B8=" + }, + "ajv": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz", + "integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=", + "requires": { + "co": "4.6.0", + "fast-deep-equal": "1.0.0", + "json-schema-traverse": "0.3.1", + "json-stable-stringify": "1.0.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "anymatch": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", + "requires": { + "micromatch": "2.3.11", + "normalize-path": "2.1.1" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz", + "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.3.3" + } + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=" + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=" + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=" + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=" + }, + "async-foreach": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz", + "integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + }, + "babel-cli": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-cli/-/babel-cli-6.26.0.tgz", + "integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=", + "dev": true, + "requires": { + "babel-core": "6.26.0", + "babel-polyfill": "6.26.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "chokidar": "1.7.0", + "commander": "2.11.0", + "convert-source-map": "1.5.0", + "fs-readdir-recursive": "1.0.0", + "glob": "7.1.2", + "lodash": "4.17.4", + "output-file-sync": "1.1.2", + "path-is-absolute": "1.0.1", + "slash": "1.0.0", + "source-map": "0.5.7", + "v8flags": "2.1.1" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "babel-core": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz", + "integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=", + "requires": { + "babel-code-frame": "6.26.0", + "babel-generator": "6.26.0", + "babel-helpers": "6.24.1", + "babel-messages": "6.23.0", + "babel-register": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "convert-source-map": "1.5.0", + "debug": "2.6.9", + "json5": "0.5.1", + "lodash": "4.17.4", + "minimatch": "3.0.4", + "path-is-absolute": "1.0.1", + "private": "0.1.7", + "slash": "1.0.0", + "source-map": "0.5.7" + } + }, + "babel-generator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-generator/-/babel-generator-6.26.0.tgz", + "integrity": "sha1-rBriAHC3n248odMmlhMFN3TyDcU=", + "requires": { + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "detect-indent": "4.0.0", + "jsesc": "1.3.0", + "lodash": "4.17.4", + "source-map": "0.5.7", + "trim-right": "1.0.1" + } + }, + "babel-helper-builder-binary-assignment-operator-visitor": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz", + "integrity": "sha1-zORReto1b0IgvK6KAsKzRvmlZmQ=", + "requires": { + "babel-helper-explode-assignable-expression": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-call-delegate": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz", + "integrity": "sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-define-map": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz", + "integrity": "sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-explode-assignable-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz", + "integrity": "sha1-8luCz33BBDPFX3BZLVdGQArCLKo=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", + "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", + "requires": { + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-get-function-arity": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", + "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-hoist-variables": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz", + "integrity": "sha1-HssnaJydJVE+rbyZFKc/VAi+enY=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-optimise-call-expression": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz", + "integrity": "sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-regex": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz", + "integrity": "sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-helper-remap-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz", + "integrity": "sha1-XsWBgnrXI/7N04HxySg5BnbkVRs=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helper-replace-supers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz", + "integrity": "sha1-v22/5Dk40XNpohPKiov3S2qQqxo=", + "requires": { + "babel-helper-optimise-call-expression": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-helpers": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-helpers/-/babel-helpers-6.24.1.tgz", + "integrity": "sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-check-es2015-constants": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz", + "integrity": "sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-syntax-async-functions": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz", + "integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU=" + }, + "babel-plugin-syntax-exponentiation-operator": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz", + "integrity": "sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4=" + }, + "babel-plugin-syntax-trailing-function-commas": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz", + "integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM=" + }, + "babel-plugin-transform-async-to-generator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz", + "integrity": "sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E=", + "requires": { + "babel-helper-remap-async-to-generator": "6.24.1", + "babel-plugin-syntax-async-functions": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-arrow-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz", + "integrity": "sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoped-functions": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz", + "integrity": "sha1-u8UbSflk1wy42OC5ToICRs46YUE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-block-scoping": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz", + "integrity": "sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "lodash": "4.17.4" + } + }, + "babel-plugin-transform-es2015-classes": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz", + "integrity": "sha1-WkxYpQyclGHlZLSyo7+ryXolhNs=", + "requires": { + "babel-helper-define-map": "6.26.0", + "babel-helper-function-name": "6.24.1", + "babel-helper-optimise-call-expression": "6.24.1", + "babel-helper-replace-supers": "6.24.1", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-computed-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz", + "integrity": "sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM=", + "requires": { + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-destructuring": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz", + "integrity": "sha1-mXux8auWf2gtKwh2/jWNYOdlxW0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-duplicate-keys": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz", + "integrity": "sha1-c+s9MQypaePvnskcU3QabxV2Qj4=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-for-of": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz", + "integrity": "sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-function-name": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz", + "integrity": "sha1-g0yJhTvDaxrw86TF26qU/Y6sqos=", + "requires": { + "babel-helper-function-name": "6.24.1", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz", + "integrity": "sha1-T1SgLWzWbPkVKAAZox0xklN3yi4=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-amd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz", + "integrity": "sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ=", + "requires": { + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-commonjs": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.0.tgz", + "integrity": "sha1-DYOUApt9xqvhqX7xgeAHWN0uXYo=", + "requires": { + "babel-plugin-transform-strict-mode": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-systemjs": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz", + "integrity": "sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM=", + "requires": { + "babel-helper-hoist-variables": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-modules-umd": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz", + "integrity": "sha1-rJl+YoXNGO1hdq22B9YCNErThGg=", + "requires": { + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0" + } + }, + "babel-plugin-transform-es2015-object-super": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz", + "integrity": "sha1-JM72muIcuDp/hgPa0CH1cusnj40=", + "requires": { + "babel-helper-replace-supers": "6.24.1", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-parameters": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz", + "integrity": "sha1-V6w1GrScrxSpfNE7CfZv3wpiXys=", + "requires": { + "babel-helper-call-delegate": "6.24.1", + "babel-helper-get-function-arity": "6.24.1", + "babel-runtime": "6.26.0", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-shorthand-properties": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz", + "integrity": "sha1-JPh11nIch2YbvZmkYi5R8U3jiqA=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-spread": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz", + "integrity": "sha1-1taKmfia7cRTbIGlQujdnxdG+NE=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-sticky-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz", + "integrity": "sha1-AMHNsaynERLN8M9hJsLta0V8zbw=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-plugin-transform-es2015-template-literals": { + "version": "6.22.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz", + "integrity": "sha1-qEs0UPfp+PH2g51taH2oS7EjbY0=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-typeof-symbol": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz", + "integrity": "sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I=", + "requires": { + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-es2015-unicode-regex": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz", + "integrity": "sha1-04sS9C6nMj9yk4fxinxa4frrNek=", + "requires": { + "babel-helper-regex": "6.26.0", + "babel-runtime": "6.26.0", + "regexpu-core": "2.0.0" + } + }, + "babel-plugin-transform-exponentiation-operator": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz", + "integrity": "sha1-KrDJx/MJj6SJB3cruBP+QejeOg4=", + "requires": { + "babel-helper-builder-binary-assignment-operator-visitor": "6.24.1", + "babel-plugin-syntax-exponentiation-operator": "6.13.0", + "babel-runtime": "6.26.0" + } + }, + "babel-plugin-transform-regenerator": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz", + "integrity": "sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8=", + "requires": { + "regenerator-transform": "0.10.1" + } + }, + "babel-plugin-transform-strict-mode": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz", + "integrity": "sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g=", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0" + } + }, + "babel-polyfill": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-polyfill/-/babel-polyfill-6.26.0.tgz", + "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", + "requires": { + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "regenerator-runtime": "0.10.5" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.10.5.tgz", + "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=" + } + } + }, + "babel-preset-env": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.0.tgz", + "integrity": "sha512-OVgtQRuOZKckrILgMA5rvctvFZPv72Gua9Rt006AiPoB0DJKGN07UmaQA+qRrYgK71MVct8fFhT0EyNWYorVew==", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-syntax-trailing-function-commas": "6.22.0", + "babel-plugin-transform-async-to-generator": "6.24.1", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-exponentiation-operator": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0", + "browserslist": "2.4.0", + "invariant": "2.2.2", + "semver": "5.4.1" + } + }, + "babel-preset-es2015": { + "version": "6.24.1", + "resolved": "https://registry.npmjs.org/babel-preset-es2015/-/babel-preset-es2015-6.24.1.tgz", + "integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=", + "dev": true, + "requires": { + "babel-plugin-check-es2015-constants": "6.22.0", + "babel-plugin-transform-es2015-arrow-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoped-functions": "6.22.0", + "babel-plugin-transform-es2015-block-scoping": "6.26.0", + "babel-plugin-transform-es2015-classes": "6.24.1", + "babel-plugin-transform-es2015-computed-properties": "6.24.1", + "babel-plugin-transform-es2015-destructuring": "6.23.0", + "babel-plugin-transform-es2015-duplicate-keys": "6.24.1", + "babel-plugin-transform-es2015-for-of": "6.23.0", + "babel-plugin-transform-es2015-function-name": "6.24.1", + "babel-plugin-transform-es2015-literals": "6.22.0", + "babel-plugin-transform-es2015-modules-amd": "6.24.1", + "babel-plugin-transform-es2015-modules-commonjs": "6.26.0", + "babel-plugin-transform-es2015-modules-systemjs": "6.24.1", + "babel-plugin-transform-es2015-modules-umd": "6.24.1", + "babel-plugin-transform-es2015-object-super": "6.24.1", + "babel-plugin-transform-es2015-parameters": "6.24.1", + "babel-plugin-transform-es2015-shorthand-properties": "6.24.1", + "babel-plugin-transform-es2015-spread": "6.22.0", + "babel-plugin-transform-es2015-sticky-regex": "6.24.1", + "babel-plugin-transform-es2015-template-literals": "6.22.0", + "babel-plugin-transform-es2015-typeof-symbol": "6.23.0", + "babel-plugin-transform-es2015-unicode-regex": "6.24.1", + "babel-plugin-transform-regenerator": "6.26.0" + } + }, + "babel-register": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz", + "integrity": "sha1-btAhFz4vy0htestFxgCahW9kcHE=", + "requires": { + "babel-core": "6.26.0", + "babel-runtime": "6.26.0", + "core-js": "2.5.1", + "home-or-tmp": "2.0.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "source-map-support": "0.4.18" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "2.5.1", + "regenerator-runtime": "0.11.0" + } + }, + "babel-template": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", + "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", + "requires": { + "babel-runtime": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lodash": "4.17.4" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "requires": { + "babel-code-frame": "6.26.0", + "babel-messages": "6.23.0", + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "debug": "2.6.9", + "globals": "9.18.0", + "invariant": "2.2.2", + "lodash": "4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "requires": { + "babel-runtime": "6.26.0", + "esutils": "2.0.2", + "lodash": "4.17.4", + "to-fast-properties": "1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "requires": { + "tweetnacl": "0.14.5" + } + }, + "binary-extensions": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.10.0.tgz", + "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=" + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "browserslist": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.4.0.tgz", + "integrity": "sha512-aM2Gt4x9bVlCUteADBS6JP0F+2tMWKM1jQzUulVROtdFWFIcIVvY76AJbr7GDqy0eDhn+PcnpzzivGxY4qiaKQ==", + "requires": { + "caniuse-lite": "1.0.30000738", + "electron-to-chromium": "1.3.22" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, + "caniuse-lite": { + "version": "1.0.30000738", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000738.tgz", + "integrity": "sha1-GCDDya25oRfjEaW9yh0lvDQojro=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "chokidar": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-1.7.0.tgz", + "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", + "requires": { + "anymatch": "1.3.2", + "async-each": "1.0.1", + "fsevents": "1.1.2", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" + } + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wrap-ansi": "2.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=" + }, + "core-js": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", + "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cross-spawn": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz", + "integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=", + "requires": { + "lru-cache": "4.1.1", + "which": "1.3.0" + } + }, + "cryptiles": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", + "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", + "requires": { + "boom": "5.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "requires": { + "array-find-index": "1.0.2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "detect-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz", + "integrity": "sha1-920GQ1LN9Docts5hnE7jqUdd4gg=", + "requires": { + "repeating": "2.0.1" + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "requires": { + "jsbn": "0.1.1" + } + }, + "electron-to-chromium": { + "version": "1.3.22", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.22.tgz", + "integrity": "sha1-QyLVLBUUBuPq73StAmdog+hBZBg=" + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "requires": { + "fill-range": "2.2.3" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", + "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=" + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", + "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs-readdir-recursive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz", + "integrity": "sha1-jNF0XItPiinIyuw5JHaSG6GV9WA=" + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.2.tgz", + "integrity": "sha512-Sn44E5wQW4bTHXvQmvSHwqbuiXtduD6Rrjm2ZtUEGbyrig+nUH3t/QD4M4/ZXViY556TBpRgZkHLDx3JxPwxiw==", + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.36" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true + }, + "co": { + "version": "4.6.0", + "bundled": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true + }, + "ini": { + "version": "1.3.4", + "bundled": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true + }, + "node-pre-gyp": { + "version": "0.6.36", + "bundled": true, + "requires": { + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true + }, + "qs": { + "version": "6.4.0", + "bundled": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true + }, + "semver": { + "version": "5.3.0", + "bundled": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true + } + } + }, + "fstream": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", + "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.2" + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "1.2.0", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "gaze": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.2.tgz", + "integrity": "sha1-hHIkZ3rbiHDWeSV+0ziP22HkAQU=", + "requires": { + "globule": "1.2.0" + } + }, + "get-caller-file": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", + "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "1.0.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "requires": { + "is-glob": "2.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==" + }, + "globule": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-1.2.0.tgz", + "integrity": "sha1-HcScaCLdnoovoAuiopUAboZkvQk=", + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "minimatch": "3.0.4" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", + "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", + "requires": { + "ajv": "5.2.3", + "har-schema": "2.0.0" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "hawk": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", + "requires": { + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.0", + "sntp": "2.0.2" + } + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "home-or-tmp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/home-or-tmp/-/home-or-tmp-2.0.0.tgz", + "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==" + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "in-publish": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz", + "integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E=" + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "requires": { + "repeating": "2.0.1" + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "invariant": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "requires": { + "loose-envify": "1.3.1" + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "requires": { + "binary-extensions": "1.10.0" + } + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=" + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=" + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "requires": { + "kind-of": "3.2.2" + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=" + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "requires": { + "isarray": "1.0.0" + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "js-base64": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", + "integrity": "sha512-Y2/+DnfJJXT1/FCwUebUhLWb3QihxiSC42+ctHLGogmW2jPY6LCapMdFZXRvVP2z6qyKW7s6qncE/9gSqZiArw==" + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "jsesc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-1.3.0.tgz", + "integrity": "sha1-RsP+yMGJKxKwgz25vHYiF226s0s=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "1.0.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "lodash.assign": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", + "integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, + "lodash.mergewith": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.0.tgz", + "integrity": "sha1-FQzwoWeR9ZA7iJHqsVRgknS96lU=" + }, + "loose-envify": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "requires": { + "js-tokens": "3.0.2" + } + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "lru-cache": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=" + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mustache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.3.0.tgz", + "integrity": "sha1-QCj3d4sXcIpImTCm5SrDvKDaQdA=", + "dev": true + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "node-gyp": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.6.2.tgz", + "integrity": "sha1-m/vlRWIoYoSDjnUOrAUpWFP6HGA=", + "requires": { + "fstream": "1.0.11", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "nopt": "3.0.6", + "npmlog": "4.1.2", + "osenv": "0.1.4", + "request": "2.83.0", + "rimraf": "2.6.2", + "semver": "5.3.0", + "tar": "2.2.1", + "which": "1.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, + "node-sass": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.5.3.tgz", + "integrity": "sha1-0JydEXlkEjnRuX/8YjH9zsU+FWg=", + "dev": true, + "requires": { + "async-foreach": "0.1.3", + "chalk": "1.1.3", + "cross-spawn": "3.0.1", + "gaze": "1.1.2", + "get-stdin": "4.0.1", + "glob": "7.1.2", + "in-publish": "2.0.0", + "lodash.assign": "4.2.0", + "lodash.clonedeep": "4.5.0", + "lodash.mergewith": "4.6.0", + "meow": "3.7.0", + "mkdirp": "0.5.1", + "nan": "2.7.0", + "node-gyp": "3.6.2", + "npmlog": "4.1.2", + "request": "2.83.0", + "sass-graph": "2.2.4", + "stdout-stream": "1.4.0" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1.1.0" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.4.tgz", + "integrity": "sha1-Qv5tWVPfBsgGS+bxdsPQWqqjRkQ=", + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "output-file-sync": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/output-file-sync/-/output-file-sync-1.1.2.tgz", + "integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=", + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "object-assign": "4.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "1.3.1" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "2.0.4" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=" + }, + "private": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", + "integrity": "sha1-aM5eih7woju1cMwoU3tTMqumPvE=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "requires": { + "is-buffer": "1.1.5" + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "readdirp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.1.0.tgz", + "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", + "requires": { + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.3", + "set-immediate-shim": "1.0.1" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regenerate": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" + }, + "regenerator-runtime": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.0.tgz", + "integrity": "sha512-/aA0kLeRb5N9K0d4fw7ooEbI+xDe+DKD499EQqygGqeS8N3xto15p09uY2xj7ixP81sNPXvRLnAQIqdVStgb1A==" + }, + "regenerator-transform": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.10.1.tgz", + "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", + "requires": { + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.7" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "regexpu-core": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-2.0.0.tgz", + "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", + "requires": { + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" + } + }, + "regjsgen": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", + "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" + }, + "regjsparser": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", + "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", + "requires": { + "jsesc": "0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" + } + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=" + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "requires": { + "is-finite": "1.0.2" + } + }, + "request": { + "version": "2.83.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "requires": { + "aws-sign2": "0.7.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.1", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "sass-graph": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", + "integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", + "requires": { + "glob": "7.1.2", + "lodash": "4.17.4", + "scss-tokenizer": "0.2.3", + "yargs": "7.1.0" + } + }, + "scss-tokenizer": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz", + "integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=", + "requires": { + "js-base64": "2.3.2", + "source-map": "0.4.4" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "set-immediate-shim": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz", + "integrity": "sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + }, + "sntp": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.0.2.tgz", + "integrity": "sha1-UGQRDwr4X3z9t9a2ekACjOUrSys=", + "requires": { + "hoek": "4.2.0" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-support": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", + "requires": { + "source-map": "0.5.7" + } + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=" + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=" + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + } + }, + "stdout-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.0.tgz", + "integrity": "sha1-osfIWH5U2UJ+qe2zrD8s1SLfN4s=", + "requires": { + "readable-stream": "2.3.3" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "0.2.1" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "requires": { + "get-stdin": "4.0.1" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "tar": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", + "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=" + }, + "trim-right": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", + "integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM=" + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + } + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "requires": { + "isexe": "2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "wide-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz", + "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "requires": { + "string-width": "1.0.2" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "1.0.2", + "strip-ansi": "3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "requires": { + "camelcase": "3.0.0", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "get-caller-file": "1.0.2", + "os-locale": "1.4.0", + "read-pkg-up": "1.0.1", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "1.0.2", + "which-module": "1.0.0", + "y18n": "3.2.1", + "yargs-parser": "5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + } + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", + "requires": { + "camelcase": "3.0.0" + }, + "dependencies": { + "camelcase": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..57b9f87 --- /dev/null +++ b/package.json @@ -0,0 +1,10 @@ +{ + "name": "iTunes Extras Template", + "version": "1.0.0", + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-preset-env": "^1.6.0", + "mustache": "^2.3.0", + "node-sass": "^4.5.3" + } +} diff --git a/src/controllers/chapters.js b/src/controllers/chapters.js new file mode 100644 index 0000000..b7da43a --- /dev/null +++ b/src/controllers/chapters.js @@ -0,0 +1,74 @@ +const chaptersController = new TKPageSliderController({ + id: 'chapters', + previousPageButton: '.carousel-previous', + nextPageButton: '.carousel-next', + outlets: [{name: 'label', selector: '.carousel-label'}], + title: _('Chapters') +}); + +chaptersController.viewDidLoad = function () { + this.view.appendChild(TKUtils.buildElement({ + type: 'emptyDiv', + className: 'carousel-previous button' + })); + this.view.appendChild(TKUtils.buildElement({ + type: 'emptyDiv', + className: 'carousel-next button' + })); + this.view.appendChild(TKUtils.buildElement({ + type: 'emptyDiv', + className: 'carousel-label' + })); + this.slidingViewData = { + sideElementsVisible: 4, + distanceBetweenElements: 800, + sideOffsetBefore: 0, + sideOffsetAfter: 0, + elements: this.createThumbnails(), + incrementalLoading: true + }; + + bookletController.registerForDisplayUpdates(this); +}; + +chaptersController.viewDidAppear = function () { + this.updateDisplay(); +}; + +chaptersController.updateDisplay = function () { + if (this.highlightedPageIndex !== (bookletController.getChapter() - 1)) { + this.highlightedPageIndex = bookletController.getChapter() - 1; + } +}; + +/* ==================== Creating Pages ==================== */ + +chaptersController.createThumbnails = function () { + let elements = []; + for (let i = 1; i <= appData.chapters.length; i++) { + let padded_index = (i < 10) ? '0' + i : i; + let url = 'images/chapters/chapter' + padded_index + '.jpg'; + elements.push({ + type: 'container', + children: [{ + type: 'container', children: [ + {type: 'image', src: url}, + {type: 'image', src: 'images/interface/buttonPlayCircle.png'} + ] + }] + }); + } + return elements; +}; + +/* ==================== Pages Navigation ==================== */ + +// called when the user focuses another page +chaptersController.pageWasHighlighted = function (index) { + this.label.textContent = appData.chapters[index]; +}; + +// called when the user activates the focused pages +chaptersController.pageWasSelected = function (index) { + bookletController.playChapter(index + 1); +}; \ No newline at end of file diff --git a/src/controllers/data.js.mustache b/src/controllers/data.js.mustache new file mode 100644 index 0000000..59023b9 --- /dev/null +++ b/src/controllers/data.js.mustache @@ -0,0 +1,25 @@ +let appData = { + feature: { + XID: "{{{ XID }}}", + title: "{{{ meta.title }}}", + artist: "{{{ meta.artist }}}" + }, + audioLoop: { + src: "audio/background.m4a", + loop: true + }, + chapters: [ + {{#chapters}}"{{{.}}}",{{/chapters}} + ], + features: [ + {{#features}} + { + title: "{{{title}}}", + description: "{{{description}}}", + src: "{{{src}}}", + imageName: "{{{imageName}}}", + duration: "{{{duration}}}" + }, + {{/features}} + ] +}; \ No newline at end of file diff --git a/src/controllers/features.js b/src/controllers/features.js new file mode 100644 index 0000000..540a448 --- /dev/null +++ b/src/controllers/features.js @@ -0,0 +1,87 @@ +let featuresHelper = {}; + +featuresHelper.createFeatureController = function (feature, index) { + let controller = new TKController({ + id: 'selection-' + index + }); + controller.viewDidLoad = function () { + this.view.classList.add('selection'); + this.view.appendChild(TKUtils.buildElement({ + type: 'container', + children: [ + { + type: 'image', + src: 'images/' + feature.imageName + }, { + type: 'image', + src: 'images/interface/buttonPlayCircle.png', + className: 'play-overlay' + }] + })); + this.view.appendChild(TKUtils.buildElement({ + type: 'div', + className: 'title', + content: feature.title + })); + this.view.appendChild(TKUtils.buildElement({ + type: 'div', + className: 'description', + content: feature.description + })); + this.view.querySelector('.play-overlay').addEventListener('click', () => { + console.log(feature); + bookletController.playNonLibraryContent({src: feature.src, string: feature.title}); + }) + }; + return controller; +} +; + +let featuresController = new TKTabController({ + id: 'features', + tabsSelector: '.list .list-item', + controllers: appData.features.map(featuresHelper.createFeatureController), + title: _('Features') +}); + +featuresController.viewDidLoad = function () { + const vignetteElement = TKUtils.buildElement({ + type: 'emptyDiv', + className: 'vignette' + }); + this.view.appendChild(vignetteElement); + this.view.addClassName('list-on-right'); + this.buildFeaturesList(appData.features); +}; + +featuresController.buildFeaturesList = function (features) { + let featureElements = features.map(feature => { + return { + type: 'container', + className: 'list-item', + children: [ + {type: 'image', src: 'images/' + feature.imageName}, + { + type: 'container', + className: 'list-item-body', + children: [ + {type: 'div', className: 'title', content: feature.title}, + {type: 'div', className: 'duration', content: formatTime(feature.duration)} + ] + } + ] + } + }); + this.view.appendChild(TKUtils.buildElement({ + type: 'container', + className: 'list', + children: [ + {type: 'div', className: 'list-title', content: _('Features')}, + { + type: 'container', + className: 'list-content', + children: featureElements + } + ] + })); +}; \ No newline at end of file diff --git a/src/controllers/home.js b/src/controllers/home.js new file mode 100644 index 0000000..c24aa71 --- /dev/null +++ b/src/controllers/home.js @@ -0,0 +1,32 @@ +const homeController = new TKController({ + id: 'home', + actions: [ + {selector: '.play', action: bookletController.playFeature} + ], + navigatesTo: [ + {selector: '.features', controller: 'features'} + ], + highlightedElement: '.play' +}); + +homeController.viewDidLoad = function () { + let mainMenuItems = []; + mainMenuItems.push({ + type: 'div', + className: 'play button', + content: _('Play') + }); + if (typeof appData.features !== 'undefined' && appData.features.length > 0) { + mainMenuItems.push({ + type: 'div', + className: 'features button', + content: _('Features') + }) + } + + this.view.appendChild(TKUtils.buildElement({ + type: 'container', + className: 'main-menu', + children: mainMenuItems + })); +}; diff --git a/src/controllers/navigation.js b/src/controllers/navigation.js new file mode 100644 index 0000000..239eac8 --- /dev/null +++ b/src/controllers/navigation.js @@ -0,0 +1,31 @@ +window.addEventListener('load', () => { + let backButtonElement = document.querySelector('#header .back'); + backButtonElement.innerHTML = _('Back'); + TKNavigationController.sharedNavigation.backButton = '.back'; +}); + +bookletController.navigationControllerWillShowController = function (navigationController, controller) { + function showBackgroundForController() { + let imagePath = 'images/'; + if (navigationController.rootController !== controller) { + imagePath += controller.id + '/' + } + imagePath += 'background.png'; + controller.view.style.backgroundImage = "url('" + imagePath + "')"; + } + + function toggleHeader() { + let headerElement = document.getElementById('header'); + let titleElement = headerElement.querySelector('.title'); + if (controller === navigationController.rootController) { + headerElement.addClassName('hidden'); + } else { + titleElement.innerHTML = controller.title; + headerElement.removeClassName('hidden'); + } + } + + toggleHeader(); + showBackgroundForController(); +}; + diff --git a/src/controllers/strings.js b/src/controllers/strings.js new file mode 100644 index 0000000..c4d1089 --- /dev/null +++ b/src/controllers/strings.js @@ -0,0 +1,37 @@ +let STRINGS_DE = { + "Back": "Zurück", + "Play": "Wiedergabe", + "Chapters": "Kapitel", + "Features": "Bonusmaterial", + "Hr.": "Std.", + "Min.": "Min.", + "Sec.": "Sek." +}; + +function _(key) { + if (key in STRINGS_DE) { + return STRINGS_DE[key] + } else { + return key + } +} + +function formatTime(timeString) { + const components = timeString.split(':').map(Number); + let formattedComponents = []; + if (components[0] > 0) { + formattedComponents.push(components[0]); + const name = components.length === 3 ? _('Hr.') : _('Min.'); + formattedComponents.push(name); + } + if (components[1] > 0) { + formattedComponents.push(components[1]); + const name = components.length === 3 ? _('Min.') : _('Sec.'); + formattedComponents.push(name); + } + if (formattedComponents.length < 4 && components.length >= 3 && components[2] > 0) { + formattedComponents.push(components[2]); + formattedComponents.push(_('Sec.')); + } + return formattedComponents.join(' '); +} \ No newline at end of file diff --git a/src/css/_functions.scss b/src/css/_functions.scss new file mode 100644 index 0000000..38eac40 --- /dev/null +++ b/src/css/_functions.scss @@ -0,0 +1,23 @@ +$directions: ( + left: 135deg, + right: -45deg, +); + +@mixin arrow($direction, $size, $thickness) { + $angle: 0; + @if map-has_key($directions, $direction) { + $angle: #{map_get($directions, $direction)} + } @else { + $angle: $direction + } + + content: ' '; + border: 0 solid; + border-right-width: $thickness; + border-bottom-width: $thickness; + display: inline-block; + padding: $size; + transform: rotate($angle); + -webkit-transform: rotate($angle); + margin-bottom: $size / 2; +} \ No newline at end of file diff --git a/src/css/_variables.scss b/src/css/_variables.scss new file mode 100644 index 0000000..b5f1af9 --- /dev/null +++ b/src/css/_variables.scss @@ -0,0 +1,124 @@ +// Global (default) Values +$page-min-width: 1280px; +$page-min-height: 720px; + +$content-margin-left: 75px; +$content-margin-right: 75px; +$content-margin-top: 140px; // Distance from top of page to top of content (ignoring the header) +$content-margin-bottom: 60px; + +$default-text-color: rgba(235, 235, 235, 1); +$default-border-color: rgba(255, 255, 255, 0.3); +$default-transition-duration: 500ms; + +$controller-change-transition-duration: $default-transition-duration; + +$default-font-family: "Helvetica Neue", "Helvetica", sans-serif; +$default-font-size: 1rem; +$default-font-weight: 300; + +$play-overlay-size: 100px; + +// Z-Indexes +$header-z-index: 10; +$carousel-controls-z-index: 2; + +// Header + +$header-left: $content-margin-left; +$header-right: $content-margin-right; +$header-top: 0; + +$header-vertical-padding: 0.8rem; +$header-horizontal-padding: 0; +$header-border-width: 1px; +$header-border-color: $default-border-color; + +$header-font-size: 1.7rem; + +$header-transition-duration: $controller-change-transition-duration; + +// Back Button + +$back-button-arrow-thickness: 1px; +$back-button-arrow-size: 4px; // TODO: Use rem instead +$back-button-arrow-text-spacer: 5px; + +$back-button-font-size: 1.1rem; +$back-button-corner-radius: 5px; +$back-button-background-color: $header-border-color; +$back-button-horizontal-padding: 10px; +$back-button-vertical-padding: 7px; + +// Main Menu +$main-menu-bottom-distance: 62px; +$main-menu-padding: 25px; +$main-menu-item-distance: 100px; + +$main-menu-font-size: 1.7rem; + +$main-menu-blur-radius: 10px; +$main-menu-background-color: rgba(0, 0, 0, 0.3); +$main-menu-border-width: 1px; +$main-menu-border-color: $default-border-color; + +// Carousel + +$carousel-top-space: $content-margin-top; +$carousel-left-margin: 0; +$carousel-right-margin: 0; + +$carousel-item-width: 800px; +$carousel-item-height: 450px; +$carousel-secondary-scale-factor: 0.75; + +$carousel-transition-duration: $default-transition-duration; + +$carousel-label-top-margin: 20px; +$carousel-label-font-size: 2.25rem; + +$carousel-control-buttons-top-margin: $carousel-top-space + 0.5 * $carousel-item-height; +$carousel-previous-left: $content-margin-left; +$carousel-next-right: $content-margin-right; +$carousel-control-buttons-size: 15px; +$carousel-control-buttons-thickness: 5px; + +// List on Right + +$lor-margin-left: $content-margin-left; +$lor-margin-right: $content-margin-right; +$lor-margin-top: $content-margin-top; +$lor-margin-bottom: $content-margin-bottom; + +$lor-list-margin-top: $lor-margin-top; +$lor-list-margin-right: $lor-margin-right; +$lor-list-margin-bottom: $lor-margin-bottom; +$lor-list-width: 320px; +$lor-list-background-color: rgba(0, 0, 0, 0.75); + +$lor-list-title-color: white; +$lor-list-title-padding: 10px; + +$lor-item-border: 1px solid $default-border-color; +$lor-item-background-color: transparent; +$lor-item-selected-background: linear-gradient(to bottom, rgba(41, 137, 216, 0.75) 0%, rgba(30, 87, 153, 0.75) 100%); +$lor-item-padding: 12px; + +$lor-item-image-width: 64px; +$lor-item-image-height: 36px; +$lor-item-title-color: white; +$lor-item-duration-sep: 5px; +$lor-item-duration-color: rgb(140, 140, 140); + +$lor-selection-width: 800px; +$lor-selection-image-max-height: 450px; +$lor-selection-title-sep: 10px; +$lor-selection-title-font-size: 1.6rem; +$lor-selection-title-color: white; +$lor-selection-description-sep: 10px; +$lor-selection-description-font-size: 1.6rem; +$lor-selection-description-font-weight: 200; +$lor-selection-description-color: rgba(255, 255, 255, 0.75); + +$lor-vignette-color: black; +$lor-vignette-size: 750px; \ No newline at end of file diff --git a/src/css/carousel.scss b/src/css/carousel.scss new file mode 100644 index 0000000..cf92789 --- /dev/null +++ b/src/css/carousel.scss @@ -0,0 +1,92 @@ +@import "variables"; +@import "functions"; + +/* Sliding View */ + +.tk-page-slider-controller-view { + .sliding-view { + position: absolute; + top: $carousel-top-space; + left: $carousel-left-margin; + right: $carousel-right-margin; + overflow: hidden; + + height: $carousel-item-height; + } + + .sliding-view-element { + position: absolute; + left: calc(50% - #{$carousel-item-width / 2}); + -webkit-transition: -webkit-transform $carousel-transition-duration; + cursor: pointer; + + div { + -webkit-transition: -webkit-transform $carousel-transition-duration; + -webkit-transform: scale($carousel-secondary-scale-factor); + } + + &.sliding-view-element-focused { + div { + -webkit-transform: scale(1); + } + } + + // The actual image of the item + div img:nth-child(1) { + width: $carousel-item-width; + height: $carousel-item-height; + } + + // The play button + div img:nth-child(2) { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + opacity: 0; + -webkit-transition: opacity $carousel-transition-duration; + } + .sliding-view-element-focused div img:nth-child(2) { + opacity: 1; + } + } + + .sliding-view-element-hidden { + display: none; + } +} + +/* Label */ + +.carousel-label { + position: absolute; + left: calc(50% - #{0.5 * $carousel-item-width}); + right: calc(50% - #{0.5 * $carousel-item-width}); + top: $carousel-top-space + $carousel-item-height + $carousel-label-top-margin; + + font-size: $carousel-label-font-size; + text-align: center; + overflow: visible; + overflow-wrap: break-word; + word-wrap: break-word; + hyphens: auto; +} + +/* Arrows */ + +.carousel-previous { + @include arrow(left, $carousel-control-buttons-size, $carousel-control-buttons-thickness); + + position: absolute; + top: $carousel-control-buttons-top-margin; + left: $carousel-previous-left; + z-index: $carousel-controls-z-index; +} + +.carousel-next { + @include arrow(right, $carousel-control-buttons-size, $carousel-control-buttons-thickness); + position: absolute; + margin-top: $carousel-control-buttons-top-margin; + right: $carousel-next-right; + z-index: $carousel-controls-z-index; +} diff --git a/src/css/home.scss b/src/css/home.scss new file mode 100644 index 0000000..621b1bf --- /dev/null +++ b/src/css/home.scss @@ -0,0 +1,26 @@ +@import "variables"; + +.main-menu { + position: absolute; + left: 0; + right: 0; + bottom: $main-menu-bottom-distance; + padding: $main-menu-padding; + + -webkit-backdrop-filter: blur($main-menu-blur-radius); + background-color: $main-menu-background-color; + border-top: $main-menu-border-width solid $main-menu-border-color; + border-bottom: $main-menu-border-width solid $main-menu-border-color; + + display: flex; + justify-content: center; + + div { + text-align: center; + font-size: $main-menu-font-size; + } + + div + div { + margin-left: $main-menu-item-distance; + } +} \ No newline at end of file diff --git a/src/css/list-on-right.scss b/src/css/list-on-right.scss new file mode 100644 index 0000000..b6277b9 --- /dev/null +++ b/src/css/list-on-right.scss @@ -0,0 +1,95 @@ +@import "variables"; + +.list-on-right .list { + position: absolute; + top: $lor-list-margin-top; + right: $lor-list-margin-right; + bottom: $lor-list-margin-bottom; + width: $lor-list-width; + background-color: $lor-list-background-color; + + display: flex; + flex-direction: column; + + .list-title { + color: $lor-list-title-color; + padding: $lor-list-title-padding; + border-bottom: $lor-item-border; + } + + .list-content { + overflow: scroll; + } + + .list-item { + background-color: $lor-item-background-color; + display: flex; + + & + .list-item { + border-top: $lor-item-border; + } + + &.tk-tab-selected { + background: $lor-item-selected-background; + } + + img { + width: $lor-item-image-width; + height: $lor-item-image-height; + margin: $lor-item-padding; + } + + .list-item-body { + flex: 1; + margin: $lor-item-padding $lor-item-padding $lor-item-padding 0; + } + + .title { + color: $lor-item-title-color; + } + + .duration { + margin-top: $lor-item-duration-sep; + color: $lor-item-duration-color; + } + } +} + +.list-on-right .selection { + position: absolute; + left: $lor-margin-left; + top: $lor-margin-top; + width: $lor-selection-width; + + div { + position: relative; + text-align: center; + } + + img:not(.play-overlay) { + max-width: 100%; + max-height: $lor-selection-image-max-height; + } + + .title { + margin-top: $lor-selection-title-sep; + font-size: $lor-selection-title-font-size; + color: $lor-selection-title-color; + } + + .description { + margin-top: $lor-selection-description-sep; + font-size: $lor-selection-description-font-size; + font-weight: $lor-selection-description-font-weight; + color: $lor-selection-description-color; + } +} + +.vignette { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + box-shadow: 0 0 $lor-vignette-size $lor-vignette-color inset; +} \ No newline at end of file diff --git a/src/css/shared.scss b/src/css/shared.scss new file mode 100644 index 0000000..4f7497d --- /dev/null +++ b/src/css/shared.scss @@ -0,0 +1,103 @@ +@import "variables"; +@import "functions"; + +* { + -webkit-user-select: none; + -webkit-user-drag: none; +} + +html { + min-width: $page-min-width; + min-height: $page-min-height; + height: 100%; +} + +body { + margin: 0; + width: 100%; + height: 100%; + + font-family: $default-font-family; + font-weight: $default-font-weight; + font-size: $default-font-size; + color: $default-text-color; +} + +#header { + position: absolute; + left: $header-left; + right: $header-right; + top: $header-top; + padding: $header-vertical-padding $header-horizontal-padding; + z-index: $header-z-index; + border-bottom: $header-border-width solid $header-border-color; + + -webkit-transition: opacity $header-transition-duration; + + text-align: center; + font-size: $header-font-size; + + .back { + position: absolute; + font-size: $back-button-font-size; + border-radius: $back-button-corner-radius; + background-color: $back-button-background-color; + padding: $back-button-vertical-padding $back-button-horizontal-padding; + + &::before { + @include arrow(left, $back-button-arrow-size, $back-button-arrow-thickness); + margin-right: $back-button-arrow-text-spacer; + } + } +} + +#navigation { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + + background-image: url("/images/background.png"); + background-size: cover; + + > div { + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + + background-size: cover; + } +} + +// Elements +.button { + cursor: pointer; + + &:active { + color: white; + } +} + +.hidden { + opacity: 0; +} + +.inactive { + opacity: 0; + pointer-events: none; +} + +.play-overlay { + position: absolute; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + + width: $play-overlay-size; + height: $play-overlay-size; + + cursor: pointer; +} \ No newline at end of file diff --git a/src/iTunesMetadata.plist.mustache b/src/iTunesMetadata.plist.mustache new file mode 100644 index 0000000..f9bdb2c --- /dev/null +++ b/src/iTunesMetadata.plist.mustache @@ -0,0 +1,58 @@ + + + + + Metadata + + artistName + {{{ meta.artist }}} + description + {{{ meta.description }}} + longDescription + {{{ meta.longDescription }}} + genre + {{{ meta.genre }}} + itemId + {{{ extrasID }}} + itemName + {{{ meta.title }}} - iTunes Extras + kind + feature-movie + releaseDate + {{{ meta.releaseDate }}} + sort-artist-status + 128 + sort-name + {{{ meta.sort-name}}} + sort-name-status + 1 + year + {{{ meta.year }}} + studio + {{{ meta.studio }}} + playlistId + {{{ movieID }}} + playlistName + {{{ meta.title }}} + xid + {{{ XID }}}_ITUNES_EXTRAS + + Name File + {{{ meta.title }}} - iTunes Extras.ite + associated-adam-ids + + {{{ movieID }}} + + xid-asset-mapping + + {{{ XID }}} + + {{{ movieID }}} + + {{{ XID }}}_ITUNES_EXTRAS + + {{{ extrasID }}} + + + + diff --git a/src/images/interface/buttonPlayCircle.png b/src/images/interface/buttonPlayCircle.png new file mode 100644 index 0000000000000000000000000000000000000000..418e3145fe614d28c5075c25d9679fb492579e75 GIT binary patch literal 73672 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 literal 0 HcmV?d00001 diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..6d7ff31 --- /dev/null +++ b/src/index.html @@ -0,0 +1,33 @@ + + + + + + + iTunes Extra for Movie + + + + + + + + + + + + + + + + + + + + + diff --git a/src/manifest.xml.mustache b/src/manifest.xml.mustache new file mode 100644 index 0000000..1aec220 --- /dev/null +++ b/src/manifest.xml.mustache @@ -0,0 +1,14 @@ + + + + + + + + + + + + +