Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/gallery.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/js/vendor
diff options
context:
space:
mode:
authorOlivier Paroz <github@oparoz.com>2015-09-08 04:15:15 +0300
committerOlivier Paroz <github@oparoz.com>2015-09-24 11:23:50 +0300
commite3a80971d036eb9e9b01c7d503280c106fc3dfa6 (patch)
treeb3535d178cb766d64ed7c13269a78918dfce0988 /js/vendor
parent011bf95bf03a7ea75672a399f8787df5d2aea37c (diff)
Add DOMPurify and cleanup JS libraries
Diffstat (limited to 'js/vendor')
-rw-r--r--js/vendor/bigshot/bigshot-2.0.zipbin1030083 -> 0 bytes
-rw-r--r--js/vendor/bigshot/bigshot.js9717
-rw-r--r--js/vendor/dompurify/purify.js694
-rw-r--r--js/vendor/eventsource-polyfill/.bower.json43
-rw-r--r--js/vendor/eventsource-polyfill/LICENSE21
-rw-r--r--js/vendor/eventsource-polyfill/README.md75
-rw-r--r--js/vendor/eventsource-polyfill/bower.json29
-rw-r--r--js/vendor/eventsource-polyfill/dist/browserify-eventsource.js23
-rw-r--r--js/vendor/eventsource-polyfill/dist/eventsource.js621
-rw-r--r--js/vendor/eventsource-polyfill/dist/eventsource.min.js1
-rw-r--r--js/vendor/github-markdown-css/.bower.json30
-rw-r--r--js/vendor/github-markdown-css/bower.json19
-rw-r--r--js/vendor/github-markdown-css/github-markdown.css649
-rw-r--r--js/vendor/github-markdown-css/license21
-rw-r--r--js/vendor/github-markdown-css/readme.md56
-rw-r--r--js/vendor/image-scale/LICENSE20
-rw-r--r--js/vendor/image-scale/README.md210
-rw-r--r--js/vendor/image-scale/image-scale.js512
-rw-r--r--js/vendor/marked/.bower.json33
-rw-r--r--js/vendor/marked/LICENSE19
-rw-r--r--js/vendor/marked/Makefile12
-rw-r--r--js/vendor/marked/README.md406
-rw-r--r--js/vendor/marked/bin/marked187
-rw-r--r--js/vendor/marked/bower.json24
-rw-r--r--js/vendor/marked/component.json10
-rw-r--r--js/vendor/marked/doc/broken.md426
-rw-r--r--js/vendor/marked/doc/todo.md2
-rw-r--r--js/vendor/marked/index.js1
-rw-r--r--js/vendor/marked/lib/marked.js1272
-rw-r--r--js/vendor/marked/man/marked.188
-rw-r--r--js/vendor/marked/package.json22
31 files changed, 694 insertions, 14549 deletions
diff --git a/js/vendor/bigshot/bigshot-2.0.zip b/js/vendor/bigshot/bigshot-2.0.zip
deleted file mode 100644
index fdfc0408..00000000
--- a/js/vendor/bigshot/bigshot-2.0.zip
+++ /dev/null
Binary files differ
diff --git a/js/vendor/bigshot/bigshot.js b/js/vendor/bigshot/bigshot.js
deleted file mode 100644
index eee39bbe..00000000
--- a/js/vendor/bigshot/bigshot.js
+++ /dev/null
@@ -1,9717 +0,0 @@
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-if (!self["bigshot"]) {
- /**
- * @namespace Bigshot namespace.
- *
- * Bigshot is a toolkit for zoomable images and VR panoramas.
- *
- * <h3>Zoomable Images</h3>
- *
- * <p>The two classes that are needed for zoomable images are:
- *
- * <ul>
- * <li>{@link bigshot.Image}: The main class for making zoomable images. See the class docs
- * for a tutorial.
- * <li>{@link bigshot.ImageParameters}: Parameters for zoomable images.
- * <li>{@link bigshot.SimpleImage}: A class for making simple zoomable images that don't
- * require the generation of an image pyramid.. See the class docs for a tutorial.
- * </ul>
- *
- * For hotspots, see:
- *
- * <ul>
- * <li>{@link bigshot.HotspotLayer}
- * <li>{@link bigshot.Hotspot}
- * <li>{@link bigshot.LabeledHotspot}
- * <li>{@link bigshot.LinkHotspot}
- * </ul>
- *
- * <h3>VR Panoramas</h3>
- *
- * <p>The two classes that are needed for zoomable VR panoramas (requires WebGL) are:
- *
- * <ul>
- * <li>{@link bigshot.VRPanorama}: The main class for making VR panoramas. See the class docs
- * for a tutorial.
- * <li>{@link bigshot.VRPanoramaParameters}: Parameters for VR panoramas.
- * </ul>
- *
- * For hotspots, see:
- *
- * <ul>
- * <li>{@link bigshot.VRHotspot}
- * <li>{@link bigshot.VRRectangleHotspot}
- * <li>{@link bigshot.VRPointHotspot}
- * </ul>
- */
- bigshot = {};
-
- /*
- * This is supposed to be processed using a minimalhttpd.IncludeProcessor
- * during development. The files must be listed in dependency order.
- */
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * This class has no constructor, it is created as an object literal.
- * @name bigshot.HomogeneousPoint3D
- * @class A 3d homogenous point.
- * @property {number} x the x-coordinate
- * @property {number} y the y-coordinate
- * @property {number} z the z-coordinate
- * @property {number} w the w-coordinate
- */
-
-/**
- * This class has no constructor, it is created as an object literal.
- * @name bigshot.Point3D
- * @class A 3d point.
- * @property {number} x the x-coordinate
- * @property {number} y the y-coordinate
- * @property {number} z the z-coordinate
- */
-
-/**
- * This class has no constructor, it is created as an object literal.
- * @name bigshot.Point2D
- * @class A 2d point.
- * @property {number} x the x-coordinate
- * @property {number} y the y-coordinate
- */
-
-/**
- * This class has no constructor, it is created as an object literal.
- * @name bigshot.Rotation
- * @class A rotation specified as a yaw-pitch-roll triplet.
- * @property {number} y the rotation around the yaw (y) axis
- * @property {number} p the rotation around the pitch (x) axis
- * @property {number} r the rotation around the roll (z) axis
- */
-
-
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Object-oriented support functions, used to make JavaScript
- * a bit more palatable to a Java-head.
- */
-bigshot.Object = {
- /**
- * Extends a base class with a derived class.
- *
- * @param {Function} derived the derived-class
- * @param {Function} base the base-class
- */
- extend : function (derived, base) {
- for (var k in base.prototype) {
- if (derived.prototype[k]) {
- derived.prototype[k]._super = base.prototype[k];
- } else {
- derived.prototype[k] = base.prototype[k];
- }
- }
- },
-
- /**
- * Resolves a name relative to <code>self</code>.
- *
- * @param {String} name the name to resolve
- * @type {Object}
- */
- resolve : function (name) {
- var c = name.split (".");
- var clazz = self;
- for (var i = 0; i < c.length; ++i) {
- clazz = clazz[c[i]];
- }
- return clazz;
- },
-
- validate : function (clazzName, iface) {
- },
-
- /**
- * Utility function to show an object's fields in a message box.
- *
- * @param {Object} o the object
- */
- alertr : function (o) {
- var sb = "";
- for (var k in o) {
- sb += k + ":" + o[k] + "\n";
- }
- alert (sb);
- },
-
- /**
- * Utility function to show an object's fields in the console log.
- *
- * @param {Object} o the object
- */
- logr : function (o) {
- var sb = "";
- for (var k in o) {
- sb += k + ":" + o[k] + "\n";
- }
- if (console) {
- console.log (sb);
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new browser helper object.
- *
- * @class Encapsulates common browser functions for cross-browser portability
- * and convenience.
- */
-bigshot.Browser = function () {
- this.requestAnimationFrameFunction =
- window.requestAnimationFrame ||
- window.mozRequestAnimationFrame ||
- window.webkitRequestAnimationFrame ||
- window.msRequestAnimationFrame ||
- function (callback, element) { return setTimeout (callback, 0); };
-}
-
-bigshot.Browser.prototype = {
- /**
- * Removes all children from an element.
- *
- * @public
- * @param {HTMLElement} element the element whose children are to be removed.
- */
- removeAllChildren : function (element) {
- element.innerHTML = "";
- /*
- if (element.children.length > 0) {
- for (var i = element.children.length - 1; i >= 0; --i) {
- element.removeChild (element.children[i]);
- }
- }
- */
- },
-
- /**
- * Thunk to implement a faked "mouseenter" event.
- * @private
- */
- mouseEnter : function (_fn) {
- var isAChildOf = this.isAChildOf;
- return function(_evt)
- {
- var relTarget = _evt.relatedTarget;
- if (this === relTarget || isAChildOf (this, relTarget))
- { return; }
-
- _fn.call (this, _evt);
- }
- },
-
- isAChildOf : function (_parent, _child) {
- if (_parent === _child) { return false; }
- while (_child && _child !== _parent)
- { _child = _child.parentNode; }
-
- return _child === _parent;
- },
-
- /**
- * Unregisters a listener from an element.
- *
- * @param {HTMLElement} elem the element
- * @param {String} eventName the event name ("click", "mouseover", etc.)
- * @param {function(e)} fn the callback function to detach
- * @param {boolean} useCapture specifies if we should unregister a listener from the capture chain.
- */
- unregisterListener : function (elem, eventName, fn, useCapture) {
- if (typeof (elem.removeEventListener) != 'undefined') {
- elem.removeEventListener (eventName, fn, useCapture);
- } else if (typeof (elem.detachEvent) != 'undefined') {
- elem.detachEvent('on' + eventName, fn);
- }
- },
-
- /**
- * Registers a listener to an element.
- *
- * @param {HTMLElement} elem the element
- * @param {String} eventName the event name ("click", "mouseover", etc.)
- * @param {function(e)} fn the callback function to attach
- * @param {boolean} useCapture specifies if we want to initiate capture.
- * See <a href="https://developer.mozilla.org/en/DOM/element.addEventListener">element.addEventListener</a>
- * on MDN for an explanation.
- */
- registerListener : function (_elem, _evtName, _fn, _useCapture) {
- if (typeof _elem.addEventListener != 'undefined')
- {
- if (_evtName === 'mouseenter')
- { _elem.addEventListener('mouseover', this.mouseEnter(_fn), _useCapture); }
- else if (_evtName === 'mouseleave')
- { _elem.addEventListener('mouseout', this.mouseEnter(_fn), _useCapture); }
- else
- { _elem.addEventListener(_evtName, _fn, _useCapture); }
- }
- else if (typeof _elem.attachEvent != 'undefined')
- {
- _elem.attachEvent('on' + _evtName, _fn);
- }
- else
- {
- _elem['on' + _evtName] = _fn;
- }
- },
-
- /**
- * Stops an event from bubbling.
- *
- * @param {Event} eventObject the event object
- */
- stopEventBubbling : function (eventObject) {
- if (eventObject) {
- if (eventObject.stopPropagation) {
- eventObject.stopPropagation ();
- } else {
- eventObject.cancelBubble = true;
- }
- }
- },
-
- /**
- * Creates a callback function that simply stops the event from bubbling.
- *
- * @example
- * var browser = new bigshot.Browser ();
- * browser.registerListener (element,
- * "mousedown",
- * browser.stopEventBubblingHandler (),
- * false);
- * @type function(event)
- * @return a new function that can be used to stop an event from bubbling
- */
- stopEventBubblingHandler : function () {
- var that = this;
- return function (event) {
- that.stopEventBubbling (event);
- return false;
- };
- },
-
- /**
- * Stops bubbling for all mouse events on the element.
- *
- * @param {HTMLElement} element the element
- */
- stopMouseEventBubbling : function (element) {
- this.registerListener (element, "mousedown", this.stopEventBubblingHandler (), false);
- this.registerListener (element, "mouseup", this.stopEventBubblingHandler (), false);
- this.registerListener (element, "mousemove", this.stopEventBubblingHandler (), false);
- },
-
- /**
- * Returns the size in pixels of the element
- *
- * @param {HTMLElement} obj the element
- * @return a size object with two integer members, w and h, for width and height respectively.
- */
- getElementSize : function (obj) {
- var size = {};
- if (obj.clientWidth) {
- size.w = obj.clientWidth;
- }
- if (obj.clientHeight) {
- size.h = obj.clientHeight;
- }
- return size;
- },
-
- /**
- * Returns true if the browser is scaling the window, such as on Mobile Safari.
- * The method used here is far from perfect, but it catches the most important use case:
- * If we are running on an iDevice and the page is zoomed out.
- */
- browserIsViewporting : function () {
- if (window.innerWidth <= screen.width) {
- return false;
- } else {
- return true;
- }
- },
-
- /**
- * Returns the device pixel scale, which is equal to the number of device
- * pixels each css pixel corresponds to. Used to render the proper level of detail
- * on mobile devices, especially when zoomed out and more detailed textures are
- * simply wasted.
- *
- * @returns The number of device pixels each css pixel corresponds to.
- * For example, if the browser is zoomed out to 50% and a div with <code>width</code>
- * set to <code>100px</code> occupies 50 physical pixels, the function will return
- * <code>0.5</code>.
- * @type number
- */
- getDevicePixelScale : function () {
- if (this.browserIsViewporting ()) {
- return screen.width / window.innerWidth;
- } else {
- return 1.0;
- }
- },
-
- /**
- * Requests an animation frame, if the API is supported
- * on the browser. If not, a <code>setTimeout</code> with
- * a timeout of zero is used.
- *
- * @param {function()} callback the animation frame render function
- * @param {HTMLElement} element the element to use when requesting an
- * animation frame
- */
- requestAnimationFrame : function (callback, element) {
- var raff = this.requestAnimationFrameFunction;
- raff (callback, element);
- },
-
- /**
- * Returns the position in pixels of the element relative
- * to the top left corner of the document.
- *
- * @param {HTMLElement} obj the element
- * @return a position object with two integer members, x and y.
- */
- getElementPosition : function (obj) {
- var position = new Object();
- position.x = 0;
- position.y = 0;
-
- var o = obj;
- while (o) {
- position.x += o.offsetLeft;
- position.y += o.offsetTop;
- if (o.clientLeft) {
- position.x += o.clientLeft;
- }
- if (o.clientTop) {
- position.y += o.clientTop;
- }
-
- if (o.x) {
- position.x += o.x;
- }
- if (o.y) {
- position.y += o.y;
- }
- o = o.offsetParent;
- }
- return position;
- },
-
- /**
- * Creates an XMLHttpRequest object.
- *
- * @type XMLHttpRequest
- * @returns a XMLHttpRequest object.
- */
- createXMLHttpRequest : function () {
- try {
- return new ActiveXObject("Msxml2.XMLHTTP");
- } catch (e) {
- }
-
- try {
- return new ActiveXObject("Microsoft.XMLHTTP");
- } catch (e) {
- }
-
- try {
- return new XMLHttpRequest();
- } catch(e) {
- }
-
- alert("XMLHttpRequest not supported");
-
- return null;
- },
-
- /**
- * Creates an opacity transition from opaque to transparent.
- * If CSS transitions aren't supported, the element is
- * immediately made transparent without a transition.
- *
- * @param {HTMLElement} element the element to fade out
- * @param {function()} onComplete function to call when
- * the transition is complete.
- */
- makeOpacityTransition : function (element, onComplete) {
- if (element.style.WebkitTransitionProperty != undefined) {
- element.style.opacity = 1.0;
- element.style.WebkitTransitionProperty = "opacity";
- element.style.WebkitTransitionTimingFunction = "linear";
- element.style.WebkitTransitionDuration = "1s";
- setTimeout (function () {
- element.addEventListener ("webkitTransitionEnd", function () {
- onComplete ();
- });
- element.style.opacity = 0.0;
- }, 0);
- } else {
- element.style.opacity = 0.0;
- onComplete ();
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates an event dispatcher.
- *
- * @class Base class for objects that dispatch events.
- */
-bigshot.EventDispatcher = function () {
- /**
- * The event listeners. Each key-value pair in the map is
- * an event name and an <code>Array</code> of listeners.
- *
- * @type Object
- */
- this.eventListeners = {};
-}
-
-bigshot.EventDispatcher.prototype = {
- /**
- * Adds an event listener to the specified event.
- *
- * @example
- * image.addEventListener ("click", function (event) { ... });
- *
- * @param {String} eventName the name of the event to add a listener for
- * @param {Function} handler function that is invoked with an event object
- * when the event is fired
- */
- addEventListener : function (eventName, handler) {
- if (this.eventListeners[eventName] == undefined) {
- this.eventListeners[eventName] = new Array ();
- }
- this.eventListeners[eventName].push (handler);
- },
-
- /**
- * Removes an event listener.
- * @param {String} eventName the name of the event to remove a listener for
- * @param {Function} handler the handler to remove
- */
- removeEventListener : function (eventName, handler) {
- if (this.eventListeners[eventName] != undefined) {
- var el = this.eventListeners[eventName];
- for (var i = 0; i < el.length; ++i) {
- if (el[i] === listener) {
- el.splice (i, 1);
- if (el.length == 0) {
- delete this.eventListeners[eventName];
- }
- break;
- }
- }
- }
- },
-
- /**
- * Fires an event.
- *
- * @param {String} eventName the name of the event to fire
- * @param {bigshot.Event} eventObject the event object to pass to the handlers
- */
- fireEvent : function (eventName, eventObject) {
- if (this.eventListeners[eventName] != undefined) {
- var el = this.eventListeners[eventName];
- for (var i = 0; i < el.length; ++i) {
- el[i](eventObject);
- }
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates an event.
- *
- * @class Base class for events. The interface is supposed to be as similar to
- * standard DOM events as possible.
- * @param {Object} data a data object whose fields will be used to set the
- * corresponding fields of the event object.
- */
-bigshot.Event = function (data) {
-
- /**
- * Indicates whether the event bubbles.
- * @default false
- * @type boolean
- */
- this.bubbles = false;
-
- /**
- * Indicates whether the event is cancelable.
- * @default false
- * @type boolean
- */
- this.cancelable = false;
-
- /**
- * The current target of the event
- * @default null
- */
- this.currentTarget = null;
-
- /**
- * Set if the preventDefault method has been called.
- * @default false
- * @type boolean
- */
- this.defaultPrevented = false;
-
- /**
- * The target to which the event is dispatched.
- * @default null
- */
- this.target = null;
-
- /**
- * The time the event was created, in milliseconds since the epoch.
- * @default the current time, as given by <code>new Date ().getTime ()</code>
- * @type number
- */
- this.timeStamp = new Date ().getTime ();
-
- /**
- * The event type.
- * @default null
- * @type String
- */
- this.type = null;
-
- /**
- * Flag indicating origin of event.
- * @default false
- * @type boolean
- */
- this.isTrusted = false;
-
- for (var k in data) {
- this[k] = data[k];
- }
-}
-
-bigshot.Event.prototype = {
- /**
- * Prevents default handling of the event.
- */
- preventDefault : function () {
- this.defaultPrevented = true;
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * Creates a new instance of the cached resource. May return
- * null, in which case that value is cached. The function
- * may be called multiple times, but a corresponding call to
- * the dispose function will always occur inbetween.
- * @name bigshot.TimedWeakReference.Create
- * @function
- */
-
-/**
- * Disposes a of the cached resource.
- * @name bigshot.TimedWeakReference.Dispose
- * @function
- * @param {Object} resource the resource that was created
- * by the create function
- */
-
-/**
- * Creates a new instance.
- *
- * @class Caches a lazy-created resource for a given time before
- * disposing it.
- *
- * @param {bigshot.TimedWeakReference.Create} create a function that creates the
- * held resource. May be called multiple times, but not without a call to
- * dispose inbetween.
- * @param {bigshot.TimedWeakReference.Dispose} dispose a function that disposes the
- * resource created by create.
- * @param {int} interval the polling interval in milliseconds. If the last
- * access time is further back than one interval, the held resource is
- * disposed (and will be re-created
- * on the next call to get).
- */
-bigshot.TimedWeakReference = function (create, dispose, interval) {
- this.object = null;
- this.hasObject = false;
- this.fnCreate = create;
- this.fnDispose = dispose;
- this.lastAccess = new Date ().getTime ();
- this.hasTimer = false;
- this.interval = interval;
-};
-
-bigshot.TimedWeakReference.prototype = {
- /**
- * Disposes of this instance. The resource is disposed.
- */
- dispose : function () {
- this.clear ();
- },
-
- /**
- * Gets the resource. The resource is created if needed.
- * The last access time is updated.
- */
- get : function () {
- if (!this.hasObject) {
- this.hasObject = true;
- this.object = this.fnCreate ();
- this.startTimer ();
- }
- this.lastAccess = new Date ().getTime ();
- return this.object;
- },
-
- /**
- * Forcibly disposes the held resource, if any.
- */
- clear : function () {
- if (this.hasObject) {
- this.hasObject = false;
- this.fnDispose (this.object);
- this.object = null;
- this.stopTimer ();
- }
- },
-
- /**
- * Stops the polling timer if it is running.
- * @private
- */
- stopTimer : function () {
- if (this.hasTimer) {
- clearTimeout (this.timerId);
- this.hasTimer = false;
- }
- },
-
- /**
- * Starts the polling timer if it isn't already running.
- * @private
- */
- startTimer : function () {
- if (!this.hasTimer) {
- var that = this;
- this.hasTimer = true;
- this.timerId = setTimeout (function () {
- that.hasTimer = false;
- that.update ();
- }, this.interval);
- }
- },
-
- /**
- * Disposes of the held resource if it hasn't been
- * accessed in {@link #interval} milliseconds.
- * @private
- */
- update : function () {
- if (this.hasObject) {
- var now = new Date ().getTime ();
- if (now - this.lastAccess > this.interval) {
- this.clear ();
- } else {
- this.startTimer ();
- }
- }
- }
-}
-
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates an image event.
- *
- * @class Base class for events dispatched by bigshot.ImageBase.
- * @param {Object} data a data object whose fields will be used to set the
- * corresponding fields of the event object.
- * @extends bigshot.Event
- * @see bigshot.ImageBase
- */
-bigshot.ImageEvent = function (data) {
- bigshot.Event.call (this, data);
-}
-
-/**
- * The image X coordinate of the event, if any.
- *
- * @name bigshot.ImageEvent#imageX
- * @field
- * @type number
- */
-
-/**
- * The image Y coordinate of the event, if any.
- *
- * @name bigshot.ImageEvent#imageY
- * @field
- * @type number
- */
-
-/**
- * The client X coordinate of the event, if any.
- *
- * @name bigshot.ImageEvent#clientX
- * @field
- * @type number
- */
-
-/**
- * The client Y coordinate of the event, if any.
- *
- * @name bigshot.ImageEvent#clientY
- * @field
- * @type number
- */
-
-/**
- * The local X coordinate of the event, if any.
- *
- * @name bigshot.ImageEvent#localX
- * @field
- * @type number
- */
-
-/**
- * The local Y coordinate of the event, if any.
- *
- * @name bigshot.ImageEvent#localY
- * @field
- * @type number
- */
-
-
-bigshot.ImageEvent.prototype = {
-};
-
-bigshot.Object.extend (bigshot.ImageEvent, bigshot.Event);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates an image event.
- *
- * @class Base class for events dispatched by bigshot.VRPanorama.
- * @param {Object} data a data object whose fields will be used to set the
- * corresponding fields of the event object.
- * @extends bigshot.Event
- * @see bigshot.VRPanorama
- */
-bigshot.VREvent = function (data) {
- bigshot.Event.call (this, data);
-}
-
-/**
- * The yaw coordinate of the event, if any.
- *
- * @name bigshot.VREvent#yaw
- * @field
- * @type number
- */
-
-/**
- * The pitch coordinate of the event, if any.
- *
- * @name bigshot.VREvent#pitch
- * @field
- * @type number
- */
-
-/**
- * The client X coordinate of the event, if any.
- *
- * @name bigshot.VREvent#clientX
- * @field
- * @type number
- */
-
-/**
- * The client Y coordinate of the event, if any.
- *
- * @name bigshot.VREvent#clientY
- * @field
- * @type number
- */
-
-/**
- * The local X coordinate of the event, if any.
- *
- * @name bigshot.VREvent#localX
- * @field
- * @type number
- */
-
-/**
- * The local Y coordinate of the event, if any.
- *
- * @name bigshot.VREvent#localY
- * @field
- * @type number
- */
-
-/**
- * A x,y,z triplet specifying a 3D ray from the viewer in the direction the
- * event took place. The same as the yaw and pitch fields, but in Cartesian
- * coordinates.
- *
- * @name bigshot.VREvent#ray
- * @field
- * @type xyz-triplet
- */
-
-
-bigshot.VREvent.prototype = {
-};
-
-bigshot.Object.extend (bigshot.VREvent, bigshot.Event);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new full-screen handler for an element.
- *
- * @class A utility class for making an element "full screen", or as close to that
- * as browser security allows. If the browser supports the <code>requestFullScreen</code>
- * API - as standard or as <code>moz</code>- or <code>webkit</code>- extensions,
- * this will be used.
- *
- * @param {HTMLElement} container the element that is to be made full screen
- */
-bigshot.FullScreen = function (container) {
- this.container = container;
-
- this.isFullScreen = false;
- this.savedBodyStyle = null;
- this.savedParent = null;
- this.savedSize = null;
- this.expanderDiv = null;
- this.restoreSize = false;
-
- this.onCloseHandlers = new Array ();
- this.onResizeHandlers = new Array ();
-
- var findFunc = function (el, list) {
- for (var i = 0; i < list.length; ++i) {
- if (el[list[i]]) {
- return list[i];
- }
- }
- return null;
- };
-
- this.requestFullScreen = findFunc (container, ["requestFullScreen", "mozRequestFullScreen", "webkitRequestFullscreen"]);
- this.cancelFullScreen = findFunc (document, ["cancelFullScreen", "mozCancelFullScreen", "webkitCancelFullscreen"]);
-
- this.restoreSize = this.requestFullScreen != null;
-}
-
-bigshot.FullScreen.prototype = {
- browser : new bigshot.Browser (),
-
- getRootElement : function () {
- return this.div;
- },
-
- /**
- * Adds a function that will run when exiting full screen mode.
- *
- * @param {function()} onClose the function to call
- */
- addOnClose : function (onClose) {
- this.onCloseHandlers.push (onClose);
- },
-
- /**
- * Notifies all <code>onClose</code> handlers.
- *
- * @private
- */
- onClose : function () {
- for (var i = 0; i < this.onCloseHandlers.length; ++i) {
- this.onCloseHandlers[i] ();
- }
- },
-
- /**
- * Adds a function that will run when the element is resized.
- *
- * @param {function()} onResize the function to call
- */
- addOnResize : function (onResize) {
- this.onResizeHandlers.push (onResize);
- },
-
- /**
- * Notifies all resize handlers.
- *
- * @private
- */
- onResize : function () {
- for (var i = 0; i < this.onResizeHandlers.length; ++i) {
- this.onResizeHandlers[i] ();
- }
- },
-
- /**
- * Begins full screen mode.
- */
- open : function () {
- this.isFullScreen = true;
-
- if (this.requestFullScreen) {
- return this.openRequestFullScreen ();
- } else {
- return this.openCompat ();
- }
- },
-
- /**
- * Makes the element really full screen using the <code>requestFullScreen</code>
- * API.
- *
- * @private
- */
- openRequestFullScreen : function () {
- this.savedSize = {
- width : this.container.style.width,
- height : this.container.style.height
- };
-
- this.container.style.width = "100%";
- this.container.style.height = "100%";
-
- var that = this;
-
- if (this.requestFullScreen == "mozRequestFullScreen") {
- /**
- * @private
- */
- var errFun = function () {
- that.container.removeEventListener ("mozfullscreenerror", errFun);
- that.isFullScreen = false;
- that.exitFullScreenHandler ();
- that.onClose ();
- };
- this.container.addEventListener ("mozfullscreenerror", errFun);
-
- /**
- * @private
- */
- var changeFun = function () {
- if (document.mozFullScreenElement !== that.container) {
- document.removeEventListener ("mozfullscreenchange", changeFun);
- that.exitFullScreenHandler ();
- } else {
- that.onResize ();
- }
- };
- document.addEventListener ("mozfullscreenchange", changeFun);
- } else {
- /**
- * @private
- */
- var changeFun = function () {
- if (document.webkitCurrentFullScreenElement !== that.container) {
- that.container.removeEventListener ("webkitfullscreenchange", changeFun);
- that.exitFullScreenHandler ();
- } else {
- that.onResize ();
- }
- };
- this.container.addEventListener ("webkitfullscreenchange", changeFun);
- }
-
- this.exitFullScreenHandler = function () {
- if (that.isFullScreen) {
- that.isFullScreen = false;
- document[that.cancelFullScreen]();
- if (that.restoreSize) {
- that.container.style.width = that.savedSize.width;
- that.container.style.height = that.savedSize.height;
- }
- that.onResize ();
- that.onClose ();
- }
- };
- this.container[this.requestFullScreen](Element.ALLOW_KEYBOARD_INPUT);
- },
-
- /**
- * Makes the element "full screen" in older browsers by covering the browser's client area.
- *
- * @private
- */
- openCompat : function () {
- this.savedParent = this.container.parentNode;
-
- this.savedSize = {
- width : this.container.style.width,
- height : this.container.style.height
- };
- this.savedBodyStyle = document.body.style.cssText;
-
- document.body.style.overflow = "hidden";
-
- this.expanderDiv = document.createElement ("div");
- this.expanderDiv.style.position = "absolute";
- this.expanderDiv.style.top = "0px";
- this.expanderDiv.style.left = "0px";
- this.expanderDiv.style.width = Math.max (window.innerWidth, document.documentElement.clientWidth) + "px";
- this.expanderDiv.style.height = Math.max (window.innerHeight, document.documentElement.clientHeight) + "px";
-
- document.body.appendChild (this.expanderDiv);
-
- this.div = document.createElement ("div");
- this.div.style.position = "fixed";
- this.div.style.top = window.pageYOffset + "px";
- this.div.style.left = window.pageXOffset + "px";
-
- this.div.style.width = window.innerWidth + "px";
- this.div.style.height = window.innerHeight + "px";
- this.div.style.zIndex = 9998;
-
- this.div.appendChild (this.container);
-
- //this.container.style.width = window.innerWidth + "px";
- //this.container.style.height = window.innerHeight + "px";
-
- document.body.appendChild (this.div);
-
- var that = this;
- var resizeHandler = function (e) {
- setTimeout (function () {
- that.div.style.width = window.innerWidth + "px";
- that.div.style.height = window.innerHeight + "px";
- setTimeout (function () {
- that.onResize ();
- }, 1);
- }, 1);
- };
-
-
- var rotationHandler = function (e) {
- that.expanderDiv.style.width = Math.max (window.innerWidth, document.documentElement.clientWidth) + "px";
- that.expanderDiv.style.height = Math.max (window.innerHeight, document.documentElement.clientHeight) + "px";
- setTimeout (function () {
- that.div.style.top = window.pageYOffset + "px";
- that.div.style.left = window.pageXOffset + "px";
- that.div.style.width = window.innerWidth + "px";
- that.div.style.height = window.innerHeight + "px";
- setTimeout (function () {
- that.onResize ();
- }, 1);
- }, 1);
- };
-
- var escHandler = function (e) {
- if (e.keyCode == 27) {
- that.exitFullScreenHandler ();
- }
- };
-
- this.exitFullScreenHandler = function () {
- that.isFullScreen = false;
- that.browser.unregisterListener (document, "keydown", escHandler);
- that.browser.unregisterListener (window, "resize", resizeHandler);
- that.browser.unregisterListener (document.body, "orientationchange", rotationHandler);
- if (that.restoreSize) {
- that.container.style.width = that.savedSize.width;
- that.container.style.height = that.savedSize.height;
- }
-
- document.body.style.cssText = that.savedBodyStyle;
-
- that.savedParent.appendChild (that.container);
- document.body.removeChild (that.div);
- document.body.removeChild (that.expanderDiv);
-
- that.onResize ();
- that.onClose ();
- setTimeout (function () {
- that.onResize ();
- }, 1);
- };
-
- this.browser.registerListener (document, "keydown", escHandler, false);
- this.browser.registerListener (window, "resize", resizeHandler, false);
- this.browser.registerListener (document.body, "orientationchange", rotationHandler, false);
-
- this.onResize ();
-
- return this.exitFullScreenHandler;
- },
-
- /**
- * Ends full screen mode.
- */
- close : function () {
- this.exitFullScreenHandler ();
- }
-};
-
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Loads image and XML data.
- */
-bigshot.DataLoader = function () {
-}
-
-bigshot.DataLoader.prototype = {
- /**
- * Loads an image.
- *
- * @param {String} url the url to load
- * @param {function(success,img)} onloaded called on complete
- */
- loadImage : function (url, onloaded) {},
-
- /**
- * Loads XML data.
- *
- * @param {String} url the url to load
- * @param {boolean} async use async request
- * @param {function(success,xml)} [onloaded] called on complete for async requests
- * @return the xml for synchronous calls
- */
- loadXml : function (url, async, onloaded) {}
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new data loader.
- *
- * @param {int} [maxRetries=0] the maximum number of times to retry requests
- * @param {String} [crossOrigin] the CORS crossOrigin parameter to use when loading images
- * @class Data loader using standard browser functions.
- * @augments bigshot.DataLoader
- */
-bigshot.DefaultDataLoader = function (maxRetries, crossOrigin) {
- this.maxRetries = maxRetries;
- this.crossOrigin = crossOrigin;
-
- if (!this.maxRetries) {
- this.maxRetries = 0;
- }
-}
-
-bigshot.DefaultDataLoader.prototype = {
- browser : new bigshot.Browser (),
-
- loadImage : function (url, onloaded) {
- var tile = document.createElement ("img");
- tile.retries = 0;
- if (this.crossOrigin != null) {
- tile.crossOrigin = this.crossOrigin;
- }
- var that = this;
- this.browser.registerListener (tile, "load", function () {
- if (onloaded) {
- onloaded (tile);
- }
- }, false);
- this.browser.registerListener (tile, "error", function () {
- tile.retries++;
- if (tile.retries <= that.maxRetries) {
- setTimeout (function () {
- tile.src = url;
- }, tile.retries * 1000);
- } else {
- if (onloaded) {
- onloaded (null);
- }
- }
- }, false);
- tile.src = url;
- return tile;
- },
-
- loadXml : function (url, synchronous, onloaded) {
- for (var tries = 0; tries <= this.maxRetries; ++tries) {
- var req = this.browser.createXMLHttpRequest ();
-
- req.open("GET", url, false);
- req.send(null);
- if(req.status == 200) {
- var xml = req.responseXML;
- if (xml != null) {
- if (onloaded) {
- onloaded (xml);
- }
- return xml;
- }
- }
-
- if (tries == that.maxRetries) {
- if (onloaded) {
- onloaded (null);
- }
- return null;
- }
- }
- }
-}
-
-bigshot.Object.validate ("bigshot.DefaultDataLoader", bigshot.DataLoader);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Data loader using standard browser functions that maintains
- * an in-memory cache of everything loaded.
- * @augments bigshot.DataLoader
- */
-bigshot.CachingDataLoader = function () {
- this.cache = {};
- this.requested = {};
- this.requestedTiles = {};
-}
-
-bigshot.CachingDataLoader.prototype = {
-
- browser : new bigshot.Browser (),
-
- loadImage : function (url, onloaded) {
- if (this.cache[url]) {
- if (onloaded) {
- onloaded (this.cache[url]);
- }
- return this.cache[url];
- } else if (this.requested[url]) {
- if (onloaded) {
- this.requested[url].push (onloaded);
- }
- return this.requestedTiles[url];
- } else {
- var that = this;
- this.requested[url] = new Array ();
- if (onloaded) {
- this.requested[url].push (onloaded);
- }
-
- var tile = document.createElement ("img");
- this.requestedTiles[url] = tile;
- this.browser.registerListener (tile, "load", function () {
- var listeners = that.requested[url];
- delete that.requested[url];
- delete that.requestedTiles[url];
- that.cache[url] = tile;
-
- for (var i = 0; i < listeners.length; ++i) {
- listeners[i] (tile);
- }
- }, false);
- tile.src = url;
- return tile;
- }
- },
-
- loadXml : function (url, async, onloaded) {
- if (this.cache[url]) {
- if (onloaded) {
- onloaded (this.cache[url]);
- }
- return this.cache[url];
- } else if (this.requested[url] && async) {
- if (onloaded) {
- this.requested[url].push (onloaded);
- }
- } else {
- var req = this.browser.createXMLHttpRequest ();
-
- if (!this.requested[url]) {
- this.requested[url] = new Array ();
- }
-
- if (async) {
- if (onloaded) {
- this.requested[url].push (onloaded);
- }
- }
-
- var that = this;
- var finishRequest = function () {
- if (that.requested[url]) {
- var xml = null;
- if(req.status == 200) {
- xml = req.responseXML;
- }
- var listeners = that.requested[url];
- delete that.requested[url];
- that.cache[url] = xml
-
- for (var i = 0; i < listeners.length; ++i) {
- listeners[i](xml);
- }
- }
- return xml;
- };
-
- if (async) {
- req.onreadystatechange = function () {
- if (req.readyState == 4) {
- finishRequest ();
- }
- };
- req.open("GET", url, true);
- req.send ();
- } else {
- req.open("GET", url, false);
- req.send ();
- return finishRequest ();
- }
- }
- }
-}
-
-bigshot.Object.validate ("bigshot.CachingDataLoader", bigshot.DataLoader);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new hotspot instance.
- *
- * @class Base class for hotspots in a {@link bigshot.HotspotLayer}. See {@link bigshot.HotspotLayer} for
- * examples.
- *
- * @param {number} x x-coordinate of the top-left corner, given in full image pixels
- * @param {number} y y-coordinate of the top-left corner, given in full image pixels
- * @param {number} w width of the hotspot, given in full image pixels
- * @param {number} h height of the hotspot, given in full image pixels
- * @see bigshot.HotspotLayer
- * @see bigshot.LabeledHotspot
- * @see bigshot.LinkHotspot
- * @constructor
- */
-bigshot.Hotspot = function (x, y, w, h) {
- var element = document.createElement ("div");
- element.style.position = "absolute";
- element.style.overflow = "visible";
-
- this.element = element;
- this.x = x;
- this.y = y;
- this.w = w;
- this.h = h;
-}
-
-bigshot.Hotspot.prototype = {
-
- browser : new bigshot.Browser (),
-
- /**
- * Lays out the hotspot in the viewport.
- *
- * @name bigshot.Hotspot#layout
- * @param x0 x-coordinate of top-left corner of the full image in css pixels
- * @param y0 y-coordinate of top-left corner of the full image in css pixels
- * @param zoomFactor the zoom factor.
- * @function
- */
- layout : function (x0, y0, zoomFactor) {
- var sx = this.x * zoomFactor + x0;
- var sy = this.y * zoomFactor + y0;
- var sw = this.w * zoomFactor;
- var sh = this.h * zoomFactor;
- this.element.style.top = sy + "px";
- this.element.style.left = sx + "px";
- this.element.style.width = sw + "px";
- this.element.style.height = sh + "px";
- },
-
- /**
- * Returns the HTMLDivElement used to show the hotspot.
- * Clients can access this element in order to style it.
- *
- * @type HTMLDivElement
- */
- getElement : function () {
- return this.element;
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new labeled hotspot instance.
- *
- * @class A point hotspot consisting of an image.
- *
- * @see bigshot.HotspotLayer
- * @param {number} x x-coordinate of the center corner, given in full image pixels
- * @param {number} y y-coordinate of the center corner, given in full image pixels
- * @param {number} w width of the hotspot, given in screen pixels
- * @param {number} h height of the hotspot, given in screen pixels
- * @param {number} xo x-offset, given in screen pixels
- * @param {number} yo y-offset, given in screen pixels
- * @param {HTMLElement} element the HTML element to position
- * @param {String} [imageUrl] the image to use as hotspot sprite
- * @augments bigshot.Hotspot
- */
-bigshot.PointHotspot = function (x, y, w, h, xo, yo, imageUrl) {
- bigshot.Hotspot.call (this, x, y, w, h);
- this.xo = xo;
- this.yo = yo;
-
- if (imageUrl) {
- var el = this.getElement ();
- el.style.backgroundImage = "url('" + imageUrl + "')";
- el.style.backgroundRepeat = "no-repeat";
- }
-}
-
-bigshot.PointHotspot.prototype = {
- /**
- * Returns the label element.
- *
- * @type HTMLDivElement
- */
- getLabel : function () {
- return this.label;
- },
-
- layout : function (x0, y0, zoomFactor) {
- var sx = this.x * zoomFactor + x0 + this.xo;
- var sy = this.y * zoomFactor + y0 + this.yo;
- this.element.style.top = sy + "px";
- this.element.style.left = sx + "px";
- this.element.style.width = this.w + "px";
- this.element.style.height = this.h + "px";
- }
-};
-
-bigshot.Object.extend (bigshot.PointHotspot, bigshot.Hotspot);
-
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Abstract interface description for a Layer.
- *
- * @class Abstract interface description for a layer.
- */
-bigshot.Layer = function () {
-}
-
-bigshot.Layer.prototype = {
- /**
- * Returns the layer container.
- *
- * @type HTMLDivElement
- */
- getContainer : function () {},
-
- /**
- * Sets the maximum number of image tiles that will be visible in the image.
- *
- * @param {int} x the number of tiles horizontally
- * @param {int} y the number of tiles vertically
- */
- setMaxTiles : function (x, y) {},
-
- /**
- * Called when the image's viewport is resized.
- *
- * @param {int} w the new width of the viewport, in css pixels
- * @param {int} h the new height of the viewport, in css pixels
- */
- resize : function (w, h) {},
-
- /**
- * Lays out the layer.
- *
- * @param {number} zoom the zoom level, adjusted for texture stretching
- * @param {number} x0 the x-coordinate of the top-left corner of the top-left tile in css pixels
- * @param {number} y0 the y-coordinate of the top-left corner of the top-left tile in css pixels
- * @param {number} tx0 column number (starting at zero) of the top-left tile
- * @param {number} ty0 row number (starting at zero) of the top-left tile
- * @param {number} size the {@link bigshot.ImageParameters#tileSize} - width of each
- * image tile in pixels - of the image
- * @param {number} stride offset (vertical and horizontal) from the top-left corner
- * of a tile to the next tile's top-left corner.
- * @param {number} opacity the opacity of the layer as a CSS opacity value.
- */
- layout : function (zoom, x0, y0, tx0, ty0, size, stride, opacity) {}
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new labeled hotspot instance.
- *
- * @class A hotspot with a label under it. The label element can be accessed using
- * the getLabel method and styled as any HTMLElement. See {@link bigshot.HotspotLayer} for
- * examples.
- *
- * @see bigshot.HotspotLayer
- * @param {number} x x-coordinate of the top-left corner, given in full image pixels
- * @param {number} y y-coordinate of the top-left corner, given in full image pixels
- * @param {number} w width of the hotspot, given in full image pixels
- * @param {number} h height of the hotspot, given in full image pixels
- * @param {String} labelText text of the label
- * @augments bigshot.Hotspot
- */
-bigshot.LabeledHotspot = function (x, y, w, h, labelText) {
- bigshot.Hotspot.call (this, x, y, w, h);
-
- this.label = document.createElement ("div");
- this.label.style.position = "relative";
- this.label.style.display = "inline-block";
-
- this.getElement ().appendChild (this.label);
- this.label.innerHTML = labelText;
- this.labelSize = this.browser.getElementSize (this.label);
-}
-
-bigshot.LabeledHotspot.prototype = {
- /**
- * Returns the label element.
- *
- * @type HTMLDivElement
- */
- getLabel : function () {
- return this.label;
- },
-
- layout : function (x0, y0, zoomFactor) {
- this.layout._super.call (this, x0, y0, zoomFactor);
- var sw = this.w * zoomFactor;
- var sh = this.h * zoomFactor;
- this.label.style.top = (sh + 4) + "px";
- this.label.style.left = ((sw - this.labelSize.w) / 2) + "px";
- }
-};
-
-bigshot.Object.extend (bigshot.LabeledHotspot, bigshot.Hotspot);
-
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new link-hotspot instance.
- *
- * @class A labeled hotspot that takes the user to another
- * location when it is clicked on. See {@link bigshot.HotspotLayer} for
- * examples.
- *
- * @see bigshot.HotspotLayer
- * @param {number} x x-coordinate of the top-left corner, given in full image pixels
- * @param {number} y y-coordinate of the top-left corner, given in full image pixels
- * @param {number} w width of the hotspot, given in full image pixels
- * @param {number} h height of the hotspot, given in full image pixels
- * @param {String} labelText text of the label
- * @param {String} url url to go to on click
- * @augments bigshot.LabeledHotspot
- * @constructor
- */
-bigshot.LinkHotspot = function (x, y, w, h, labelText, url) {
- bigshot.LabeledHotspot.call (this, x, y, w, h, labelText);
- this.browser.registerListener (this.getElement (), "click", function () {
- document.location.href = url;
- });
-};
-
-bigshot.Object.extend (bigshot.LinkHotspot, bigshot.LabeledHotspot);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new hotspot layer. The layer must be added to the image using
- * {@link bigshot.ImageBase#addLayer}.
- *
- * @class A hotspot layer.
- * @example
- * var image = new bigshot.Image (...);
- * var hotspotLayer = new bigshot.HotspotLayer (image);
- * var hotspot = new bigshot.LinkHotspot (100, 100, 200, 100,
- * "Bigshot on Google Code",
- * "http://code.google.com/p/bigshot/");
- *
- * // Style the hotspot a bit
- * hotspot.getElement ().className = "hotspot";
- * hotspot.getLabel ().className = "label";
- *
- * hotspotLayer.addHotspot (hotspot);
- *
- * image.addLayer (hotspotLayer);
- *
- * @param {bigshot.ImageBase} image the image this hotspot layer will be part of
- * @augments bigshot.Layer
- * @constructor
- */
-bigshot.HotspotLayer = function (image) {
- this.image = image;
- this.hotspots = new Array ();
- this.browser = new bigshot.Browser ();
- this.container = image.createLayerContainer ();
- this.parentContainer = image.getContainer ();
- this.resize (0, 0);
-}
-
-bigshot.HotspotLayer.prototype = {
-
- getContainer : function () {
- return this.container;
- },
-
- resize : function (w, h) {
- this.container.style.width = this.parentContainer.clientWidth + "px";
- this.container.style.height = this.parentContainer.clientHeight + "px";
- },
-
- layout : function (zoom, x0, y0, tx0, ty0, size, stride, opacity) {
- var zoomFactor = Math.pow (2, this.image.getZoom ());
- x0 -= stride * tx0;
- y0 -= stride * ty0;
- for (var i = 0; i < this.hotspots.length; ++i) {
- this.hotspots[i].layout (x0, y0, zoomFactor);
- }
- },
-
- setMaxTiles : function (mtx, mty) {
- },
-
- /**
- * Adds a hotspot to the layer.
- *
- * @param {bigshot.Hotspot} hotspot the hotspot to add.
- */
- addHotspot : function (hotspot) {
- this.container.appendChild (hotspot.getElement ());
- this.hotspots.push (hotspot);
- }
-}
-
-bigshot.Object.validate ("bigshot.HotspotLayer", bigshot.Layer);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new image layer.
- *
- * @param {bigshot.ImageBase} image the image that this layer is part of
- * @param {bigshot.ImageParameters} parameters the associated image parameters
- * @param {number} w the current width in css pixels of the viewport
- * @param {number} h the current height in css pixels of the viewport
- * @param {bigshot.ImageTileCache} itc the tile cache to use
- * @class A tiled, zoomable image layer.
- * @constructor
- */
-bigshot.TileLayer = function (image, parameters, w, h, itc) {
- this.rows = new Array ();
- this.browser = new bigshot.Browser ();
- this.container = image.createLayerContainer ();
- this.parentContainer = image.getContainer ();
- this.parameters = parameters;
- this.w = w;
- this.h = h;
- this.imageTileCache = itc;
-
- this.resize (w, h);
- return this;
-}
-
-bigshot.TileLayer.prototype = {
- getContainer : function () {
- return this.container;
- },
-
- resize : function (w, h) {
- this.container.style.width = this.parentContainer.clientWidth + "px";
- this.container.style.height = this.parentContainer.clientHeight + "px";
- this.pixelWidth = this.parentContainer.clientWidth;
- this.pixelHeight = this.parentContainer.clientHeight;
- this.w = w;
- this.h = h;
- this.rows = new Array ();
- this.browser.removeAllChildren (this.container);
- for (var r = 0; r < h; ++r) {
- var row = new Array ();
- for (var c = 0; c < w; ++c) {
- var tileAnchor = document.createElement ("div");
- tileAnchor.style.position = "absolute";
- tileAnchor.style.overflow = "hidden";
- tileAnchor.style.width = this.container.clientWidth + "px";
- tileAnchor.style.height = this.container.clientHeight + "px";
-
- var tile = document.createElement ("div");
- tile.style.position = "relative";
- tile.style.border = "hidden";
- tile.style.visibility = "hidden";
- tile.bigshotData = {
- visible : false
- };
- row.push (tile);
- this.container.appendChild (tileAnchor);
- tileAnchor.appendChild (tile);
- }
- this.rows.push (row);
- }
- },
-
- layout : function (zoom, x0, y0, tx0, ty0, size, stride, opacity) {
- zoom = Math.min (0, Math.ceil (zoom));
-
- this.imageTileCache.resetUsed ();
- var y = y0;
-
- var visible = 0;
- for (var r = 0; r < this.h; ++r) {
- var x = x0;
- for (var c = 0; c < this.w; ++c) {
- var tile = this.rows[r][c];
- var bigshotData = tile.bigshotData;
- if (x + size < 0 || x > this.pixelWidth || y + size < 0 || y > this.pixelHeight) {
- if (bigshotData.visible) {
- bigshotData.visible = false;
- tile.style.visibility = "hidden";
- }
- } else {
- visible++;
- tile.style.left = x + "px";
- tile.style.top = y + "px";
- tile.style.width = size + "px";
- tile.style.height = size + "px";
- tile.style.opacity = opacity;
- if (!bigshotData.visible) {
- bigshotData.visible = true;
- tile.style.visibility = "visible";
- }
- var tx = c + tx0;
- var ty = r + ty0;
- if (this.parameters.wrapX) {
- if (tx < 0 || tx >= this.imageTileCache.maxTileX) {
- tx = (tx + this.imageTileCache.maxTileX) % this.imageTileCache.maxTileX;
- }
- }
-
- if (this.parameters.wrapY) {
- if (ty < 0 || ty >= this.imageTileCache.maxTileY) {
- ty = (ty + this.imageTileCache.maxTileY) % this.imageTileCache.maxTileY;
- }
- }
-
- var imageKey = tx + "_" + ty + "_" + zoom;
- var isOutside = tx < 0 || tx >= this.imageTileCache.maxTileX || ty < 0 || ty >= this.imageTileCache.maxTileY;
- if (isOutside) {
- if (!bigshotData.isOutside) {
- var image = this.imageTileCache.getImage (tx, ty, zoom);
-
- this.browser.removeAllChildren (tile);
- tile.appendChild (image);
- bigshotData.image = image;
- }
- bigshotData.isOutside = true;
- bigshotData.imageKey = "EMPTY";
- bigshotData.image.style.width = size + "px";
- bigshotData.image.style.height = size + "px";
- } else {
- var image = this.imageTileCache.getImage (tx, ty, zoom);
-
- bigshotData.isOutside = false;
-
- if (bigshotData.imageKey !== imageKey || bigshotData.isPartial) {
- this.browser.removeAllChildren (tile);
- tile.appendChild (image);
- bigshotData.image = image;
- bigshotData.imageKey = imageKey;
- bigshotData.isPartial = image.isPartial;
- }
- bigshotData.image.style.width = size + "px";
- bigshotData.image.style.height = size + "px";
-
- }
- }
- x += stride;
- }
- y += stride;
- }
- },
-
- setMaxTiles : function (mtx, mty) {
- this.imageTileCache.setMaxTiles (mtx, mty);
- }
-};
-
-bigshot.Object.validate ("bigshot.TileLayer", bigshot.Layer);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new, empty, LRUMap instance.
- *
- * @class Implementation of a Least-Recently-Used cache map.
- * Used by the ImageTileCache to keep track of cache entries.
- * @constructor
- */
-bigshot.LRUMap = function () {
- /**
- * Key to last-accessed time mapping.
- *
- * @type Object
- */
- this.keyToTime = {};
-
- /**
- * Current time counter. Incremented for each access of
- * a key in the map.
- * @type int
- */
- this.counter = 0;
-
- /**
- * Current size of the map.
- * @type int
- */
- this.size = 0;
-}
-
-bigshot.LRUMap.prototype = {
- /**
- * Marks access to an item, represented by its key in the map.
- * The key's last-accessed time is updated to the current time
- * and the current time is incremented by one step.
- *
- * @param {String} key the key associated with the accessed item
- */
- access : function (key) {
- this.remove (key);
- this.keyToTime[key] = this.counter;
- ++this.counter;
- ++this.size;
- },
-
- /**
- * Removes a key from the map.
- *
- * @param {String} key the key to remove
- * @returns true iff the key existed in the map.
- * @type boolean
- */
- remove : function (key) {
- if (this.keyToTime[key]) {
- delete this.keyToTime[key];
- --this.size;
- return true;
- } else {
- return false;
- }
- },
-
- /**
- * Returns the current number of keys in the map.
- * @type int
- */
- getSize : function () {
- return this.size;
- },
-
- /**
- * Returns the key in the map with the lowest
- * last-accessed time. This is done as a linear
- * search through the map. It could be done much
- * faster with a sorted map, but unless this becomes
- * a bottleneck it is just not worth the effort.
- * @type String
- */
- leastUsed : function () {
- var least = this.counter + 1;
- var leastKey = null;
- for (var k in this.keyToTime) {
- if (this.keyToTime[k] < least) {
- least = this.keyToTime[k];
- leastKey = k;
- }
- }
- return leastKey;
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new cache instance.
- *
- * @class Tile cache for the {@link bigshot.TileLayer}.
- * @constructor
- */
-bigshot.ImageTileCache = function (onLoaded, onCacheInit, parameters) {
- var that = this;
-
- this.parameters = parameters;
-
- /**
- * Reduced-resolution preview of the full image.
- * Loaded from the "poster" image created by
- * MakeImagePyramid
- *
- * @private
- * @type HTMLImageElement
- */
- this.fullImage = null;
- parameters.dataLoader.loadImage (parameters.fileSystem.getPosterFilename (), function (tile) {
- that.fullImage = tile;
- if (onCacheInit) {
- onCacheInit ();
- }
- });
-
- /**
- * Maximum number of tiles in the cache.
- * @private
- * @type int
- */
- this.maxCacheSize = 512;
- this.maxTileX = 0;
- this.maxTileY = 0;
- this.cachedImages = {};
- this.requestedImages = {};
- this.usedImages = {};
- this.lastOnLoadFiredAt = 0;
- this.imageRequests = 0;
- this.lruMap = new bigshot.LRUMap ();
- this.onLoaded = onLoaded;
- this.browser = new bigshot.Browser ();
- this.partialImageSize = parameters.tileSize / 4;
- this.POSTER_ZOOM_LEVEL = Math.log (parameters.posterSize / Math.max (parameters.width, parameters.height)) / Math.log (2);
-}
-
-bigshot.ImageTileCache.prototype = {
- resetUsed : function () {
- this.usedImages = {};
- },
-
- setMaxTiles : function (mtx, mty) {
- this.maxTileX = mtx;
- this.maxTileY = mty;
- },
-
- getPartialImage : function (tileX, tileY, zoomLevel) {
- var img = this.getPartialImageFromDownsampled (tileX, tileY, zoomLevel, 0, 0, this.parameters.tileSize, this.parameters.tileSize);
- if (img == null) {
- img = this.getPartialImageFromPoster (tileX, tileY, zoomLevel);
- }
- return img;
- },
-
- getPartialImageFromPoster : function (tileX, tileY, zoomLevel) {
- if (this.fullImage && this.fullImage.complete) {
- var posterScale = this.fullImage.width / this.parameters.width;
- var tileSizeAtZoom = posterScale * this.parameters.tileSize / Math.pow (2, zoomLevel);
-
- x0 = Math.floor (tileSizeAtZoom * tileX);
- y0 = Math.floor (tileSizeAtZoom * tileY);
- w = Math.floor (tileSizeAtZoom);
- h = Math.floor (tileSizeAtZoom);
-
- return this.createPartialImage (this.fullImage, this.fullImage.width, x0, y0, w, h);
- } else {
- return null;
- }
- },
-
- createPartialImage : function (sourceImage, expectedSourceImageSize, x0, y0, w, h) {
- var canvas = document.createElement ("canvas");
- if (!canvas["width"]) {
- return null;
- }
- canvas.width = this.partialImageSize;
- canvas.height = this.partialImageSize;
- var ctx = canvas.getContext('2d');
-
- var scale = sourceImage.width / expectedSourceImageSize;
-
- var sx = Math.floor (x0 * scale);
- var sy = Math.floor (y0 * scale);
- var dw = this.partialImageSize;
- var dh = this.partialImageSize;
-
- w *= scale;
- if (sx + w >= sourceImage.width) {
- var w0 = w;
- w = sourceImage.width - sx;
- dw *= w / w0;
- }
-
- h *= scale;
- if (sy + h >= sourceImage.height) {
- var h0 = h;
- h = sourceImage.height - sy;
- dh *= h / h0;
- }
-
- try {
- ctx.drawImage (sourceImage, sx, sy, w, h, -0.1, -0.1, dw + 0.2, dh + 0.2);
- } catch (e) {
- // DOM INDEX error on iPad.
- return null;
- }
-
- return canvas;
- },
-
- getPartialImageFromDownsampled : function (tileX, tileY, zoomLevel, x0, y0, w, h) {
- // Give up if the poster image has higher resolution.
- if (zoomLevel < this.POSTER_ZOOM_LEVEL || zoomLevel < this.parameters.minZoom) {
- return null;
- }
-
- var key = this.getImageKey (tileX, tileY, zoomLevel);
- var sourceImage = this.cachedImages[key];
-
- if (sourceImage == null) {
- this.requestImage (tileX, tileY, zoomLevel);
- }
-
- if (sourceImage) {
- return this.createPartialImage (sourceImage, this.parameters.tileSize, x0, y0, w, h);
- } else {
- w /= 2;
- h /= 2;
- x0 /= 2;
- y0 /= 2;
- if ((tileX % 2) == 1) {
- x0 += this.parameters.tileSize / 2;
- }
- if ((tileY % 2) == 1) {
- y0 += this.parameters.tileSize / 2;
- }
- tileX = Math.floor (tileX / 2);
- tileY = Math.floor (tileY / 2);
- --zoomLevel;
- return this.getPartialImageFromDownsampled (tileX, tileY, zoomLevel, x0, y0, w, h);
- }
- },
-
- getEmptyImage : function () {
- var tile = document.createElement ("img");
- if (this.parameters.emptyImage) {
- tile.src = this.parameters.emptyImage;
- } else {
- tile.src = "data:image/gif,GIF89a%01%00%01%00%80%00%00%00%00%00%FF%FF%FF!%F9%04%00%00%00%00%00%2C%00%00%00%00%01%00%01%00%00%02%02D%01%00%3B";
- }
- return tile;
- },
-
- getImage : function (tileX, tileY, zoomLevel) {
- if (tileX < 0 || tileY < 0 || tileX >= this.maxTileX || tileY >= this.maxTileY) {
- return this.getEmptyImage ();
- }
-
- var key = this.getImageKey (tileX, tileY, zoomLevel);
- this.lruMap.access (key);
-
- if (this.cachedImages[key]) {
- if (this.usedImages[key]) {
- var tile = this.parameters.dataLoader.loadImage (this.getImageFilename (tileX, tileY, zoomLevel));
- tile.isPartial = false;
- return tile;
- } else {
- this.usedImages[key] = true;
- var img = this.cachedImages[key];
- return img;
- }
- } else {
- this.requestImage (tileX, tileY, zoomLevel);
- var img = this.getPartialImage (tileX, tileY, zoomLevel);
- if (img != null) {
- img.isPartial = true;
- this.cachedImages[key] = img;
- } else {
- img = this.getEmptyImage ();
- if (img != null) {
- img.isPartial = true;
- }
- }
- return img;
- }
- },
-
- requestImage : function (tileX, tileY, zoomLevel) {
- var key = this.getImageKey (tileX, tileY, zoomLevel);
- if (!this.requestedImages[key]) {
- this.imageRequests++;
- var that = this;
- this.requestedImages[key] = true;
- this.parameters.dataLoader.loadImage (this.getImageFilename (tileX, tileY, zoomLevel), function (tile) {
- delete that.requestedImages[key];
- that.imageRequests--;
- tile.isPartial = false;
- that.cachedImages[key] = tile;
- that.fireOnLoad ();
- });
- }
- },
-
- /**
- * Fires the onload event, if it hasn't been fired for at least 50 ms
- */
- fireOnLoad : function () {
- var now = new Date();
- if (this.imageRequests == 0 || now.getTime () > (this.lastOnLoadFiredAt + 50)) {
- this.purgeCache ();
- this.lastOnLoadFiredAt = now.getTime ();
- this.onLoaded ();
- }
- },
-
- /**
- * Removes the least-recently used objects from the cache,
- * if the size of the cache exceeds the maximum cache size.
- * A maximum of four objects will be removed per call.
- *
- * @private
- */
- purgeCache : function () {
- for (var i = 0; i < 4; ++i) {
- if (this.lruMap.getSize () > this.maxCacheSize) {
- var leastUsed = this.lruMap.leastUsed ();
- this.lruMap.remove (leastUsed);
- delete this.cachedImages[leastUsed];
- }
- }
- },
-
- getImageKey : function (tileX, tileY, zoomLevel) {
- return "I" + tileX + "_" + tileY + "_" + zoomLevel;
- },
-
- getImageFilename : function (tileX, tileY, zoomLevel) {
- var f = this.parameters.fileSystem.getImageFilename (tileX, tileY, zoomLevel);
- return f;
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new image parameter object and populates it with default values for
- * all values not explicitly given.
- *
- * @class ImageParameters parameter object.
- * You need not set any fields that can be read from the image descriptor that
- * MakeImagePyramid creates. See the {@link bigshot.Image} documentation for
- * required parameters.
- *
- * <p>Usage:
- *
- * @example
- * var bsi = new bigshot.Image (
- * new bigshot.ImageParameters ({
- * basePath : "/bigshot.php?file=myshot.bigshot",
- * fileSystemType : "archive",
- * container : document.getElementById ("bigshot_div")
- * }));
- *
- * @param values named parameter map, see the fields below for parameter names and types.
- * @see bigshot.Image
- */
-bigshot.ImageParameters = function (values) {
- /**
- * Size of low resolution preview image along the longest image
- * dimension. The preview is assumed to have the same aspect
- * ratio as the full image (specified by width and height).
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type int
- * @public
- */
- this.posterSize = 0;
-
- /**
- * Url for the image tile to show while the tile is loading and no
- * low-resolution preview is available.
- *
- * @default <code>null</code>, which results in an all-black image
- * @type String
- * @public
- */
- this.emptyImage = null;
-
- /**
- * Suffix to append to the tile filenames. Typically <code>".jpg"</code> or
- * <code>".png"</code>.
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type String
- */
- this.suffix = null;
-
- /**
- * The width of the full image; in pixels.
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.width = 0;
-
- /**
- * The height of the full image; in pixels.
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.height = 0;
-
- /**
- * For {@link bigshot.Image} and {@link bigshot.SimpleImage}, the <code>div</code>
- * to use as a container for the image.
- *
- * @type HTMLDivElement
- */
- this.container = null;
-
- /**
- * The minimum zoom value. Zoom values are specified as a magnification; where
- * 2<sup>n</sup> is the magnification and n is the zoom value. So a zoom value of
- * 2 means a 4x magnification of the full image. -3 means showing an image that
- * is a eighth (1/8 or 1/2<sup>3</sup>) of the full size.
- *
- * @type number
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- */
- this.minZoom = 0.0;
-
- /**
- * The maximum zoom value. Zoom values are specified as a magnification; where
- * 2<sup>n</sup> is the magnification and n is the zoom value. So a zoom value of
- * 2 means a 4x magnification of the full image. -3 means showing an image that
- * is a eighth (1/8 or 1/2<sup>3</sup>) of the full size.
- *
- * @type number
- * @default 0.0
- */
- this.maxZoom = 0.0;
-
- /**
- * Size of one tile in pixels.
- *
- * @type int
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- */
- this.tileSize = 0;
-
- /**
- * Tile overlap. Not implemented.
- *
- * @type int
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- */
- this.overlap = 0;
-
- /**
- * Flag indicating that the image should wrap horizontally. The image wraps on tile
- * boundaries; so in order to get a seamless wrap at zoom level -n; the image width must
- * be evenly divisible by <code>tileSize * 2^n</code>. Set the minZoom value appropriately.
- *
- * @type boolean
- * @default false
- */
- this.wrapX = false;
-
- /**
- * Flag indicating that the image should wrap vertically. The image wraps on tile
- * boundaries; so in order to get a seamless wrap at zoom level -n; the image height must
- * be evenly divisible by <code>tileSize * 2^n</code>. Set the minZoom value appropriately.
- *
- * @type boolean
- * @default false
- */
- this.wrapY = false;
-
- /**
- * Base path for the image. This is filesystem dependent; but for the two most common cases
- * the following should be set
- *
- * <ul>
- * <li><b>archive</b>= The basePath is <code>"&lt;path&gt;/bigshot.php?file=&lt;path-to-bigshot-archive-relative-to-bigshot.php&gt;"</code>;
- * for example; <code>"/bigshot.php?file=images/bigshot-sample.bigshot"</code>.
- * <li><b>folder</b>= The basePath is <code>"&lt;path-to-image-folder&gt;"</code>;
- * for example; <code>"/images/bigshot-sample"</code>.
- * </ul>
- *
- * @type String
- */
- this.basePath = null;
-
- /**
- * The file system type. Used to create a filesystem instance unless
- * the fileSystem field is set. Possible values are <code>"archive"</code>,
- * <code>"folder"</code> or <code>"dzi"</code>.
- *
- * @type String
- * @default "folder"
- */
- this.fileSystemType = "folder";
-
- /**
- * A reference to a filesystem implementation. If set; it overrides the
- * fileSystemType field.
- *
- * @default set depending on value of bigshot.ImageParameters.fileSystemType
- * @type bigshot.FileSystem
- */
- this.fileSystem = null;
-
- /**
- * Object used to load data files.
- *
- * @default bigshot.DefaultDataLoader
- * @type bigshot.DataLoader
- */
- this.dataLoader = new bigshot.DefaultDataLoader ();
-
- /**
- * Enable the touch-friendly ui. The touch-friendly UI splits the viewport into
- * three click-sensitive regions:
- * <p style="text-align:center"><img src="../images/touch-ui.png"/></p>
- *
- * <p>Clicking (or tapping with a finger) on the outer region causes the viewport to zoom out.
- * Clicking anywhere within the middle, "pan", region centers the image on the spot clicked.
- * Finally, clicking in the center hotspot will center the image on the spot clicked and zoom
- * in half a zoom level.
- *
- * <p>As before, you can drag to pan anywhere.
- *
- * <p>If you have navigation tools for mouse users that hover over the image container, it
- * is recommended that any click events on them are kept from bubbling, otherwise the click
- * will propagate to the touch ui. One way is to use the
- * {@link bigshot.Browser#stopMouseEventBubbling} method:
- *
- * @example
- * var browser = new bigshot.Browser ();
- * browser.stopMouseEventBubbling (document.getElementById ("myBigshotControlDiv"));
- *
- * @see bigshot.ImageBase#showTouchUI
- *
- * @type boolean
- * @default true
- * @deprecated Bigshot supports all common touch-gestures.
- */
- this.touchUI = false;
-
- /**
- * Lets you "fling" the image.
- *
- * @type boolean
- * @default true
- */
- this.fling = true;
-
- /**
- * The maximum amount that a tile will be stretched until we try to show
- * the next more detailed level.
- *
- * @type float
- * @default 1.0
- */
- this.maxTextureMagnification = 1.0;
-
- if (values) {
- for (var k in values) {
- this[k] = values[k];
- }
- }
-
- this.merge = function (values, overwrite) {
- for (var k in values) {
- if (overwrite || !this[k]) {
- this[k] = values[k];
- }
- }
- }
- return this;
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * Sets up base image functionality.
- *
- * @param {bigshot.ImageParameters} parameters the image parameters
- * @class Base class for image viewers.
- * @extends bigshot.EventDispatcher
- */
-bigshot.ImageBase = function (parameters) {
- // Base class init
- bigshot.EventDispatcher.call (this);
-
- this.parameters = parameters;
- this.flying = 0;
- this.container = parameters.container;
- this.x = parameters.width / 2.0;
- this.y = parameters.height / 2.0;
- this.zoom = 0.0;
- this.width = parameters.width;
- this.height = parameters.height;
- this.minZoom = parameters.minZoom;
- this.maxZoom = parameters.maxZoom;
- this.tileSize = parameters.tileSize;
- this.overlap = 0;
- this.imageTileCache = null;
-
- this.dragStart = null;
- this.dragged = false;
-
- this.layers = new Array ();
-
- this.fullScreenHandler = null;
- this.currentGesture = null;
-
- var that = this;
- this.onresizeHandler = function (e) {
- that.onresize ();
- }
-
- /**
- * Helper function to consume events.
- * @private
- */
- var consumeEvent = function (event) {
- if (event.preventDefault) {
- event.preventDefault ();
- }
- return false;
- };
-
- /**
- * Helper function to translate touch events to mouse-like events.
- * @private
- */
- var translateEvent = function (event) {
- if (event.clientX) {
- return event;
- } else {
- return {
- clientX : event.changedTouches[0].clientX,
- clientY : event.changedTouches[0].clientY,
- changedTouches : event.changedTouches
- };
- };
- };
-
- this.setupLayers ();
-
- this.resize ();
-
- this.allListeners = {
- "DOMMouseScroll" : function (e) {
- that.mouseWheel (e);
- return consumeEvent (e);
- },
- "mousewheel" : function (e) {
- that.mouseWheel (e);
- return consumeEvent (e);
- },
- "dblclick" : function (e) {
- that.mouseDoubleClick (e);
- return consumeEvent (e);
- },
- "mousedown" : function (e) {
- that.dragMouseDown (e);
- return consumeEvent (e);
- },
- "gesturestart" : function (e) {
- that.gestureStart (e);
- return consumeEvent (e);
- },
- "gesturechange" : function (e) {
- that.gestureChange (e);
- return consumeEvent (e);
- },
- "gestureend" : function (e) {
- that.gestureEnd (e);
- return consumeEvent (e);
- },
- "touchstart" : function (e) {
- that.dragMouseDown (translateEvent (e));
- return consumeEvent (e);
- },
- "mouseup" : function (e) {
- that.dragMouseUp (e);
- return consumeEvent (e);
- },
- "touchend" : function (e) {
- that.dragMouseUp (translateEvent (e));
- return consumeEvent (e);
- },
- "mousemove" : function (e) {
- that.dragMouseMove (e);
- return consumeEvent (e);
- },
- "mouseout" : function (e) {
- //that.dragMouseUp (e);
- return consumeEvent (e);
- },
- "touchmove" : function (e) {
- that.dragMouseMove (translateEvent (e));
- return consumeEvent (e);
- }
- };
-
- this.addEventListeners ();
- this.browser.registerListener (window, 'resize', that.onresizeHandler, false);
- this.zoomToFit ();
-}
-
-bigshot.ImageBase.prototype = {
- /**
- * Browser helper and compatibility functions.
- *
- * @private
- * @type bigshot.Browser
- */
- browser : new bigshot.Browser (),
-
- /**
- * Adds all event listeners to the container object.
- * @private
- */
- addEventListeners : function () {
- for (var k in this.allListeners) {
- this.browser.registerListener (this.container, k, this.allListeners[k], false);
- }
- },
-
- /**
- * Removes all event listeners from the container object.
- * @private
- */
- removeEventListeners : function () {
- for (var k in this.allListeners) {
- this.browser.unregisterListener (this.container, k, this.allListeners[k], false);
- }
- },
-
- /**
- * Sets up the initial layers of the image. Override in subclass.
- */
- setupLayers : function () {
- },
-
- /**
- * Returns the base 2 logarithm of the maximum texture stretching, allowing for device pixel scaling.
- * @type number
- * @private
- */
- getTextureStretch : function () {
- var ts = Math.log (this.parameters.maxTextureMagnification / this.browser.getDevicePixelScale ()) / Math.LN2;
- return ts;
- },
-
- /**
- * Constrains the x and y coordinates to allowed values
- * @param {number} x the initial x coordinate
- * @param {number} y the initial y coordinate
- * @return {number} .x the constrained x coordinate
- * @return {number} .y the constrained y coordinate
- */
- clampXY : function (x, y) {
- var viewportWidth = this.container.clientWidth;
- var viewportHeight = this.container.clientHeight;
-
- var realZoomFactor = Math.pow (2, this.zoom);
- /*
- Constrain X and Y
- */
- var viewportWidthInImagePixels = viewportWidth / realZoomFactor;
- var viewportHeightInImagePixels = viewportHeight / realZoomFactor;
-
- var constrain = function (viewportSizeInImagePixels, imageSizeInImagePixels, p) {
- var min = viewportSizeInImagePixels / 2;
- min = Math.min (imageSizeInImagePixels / 2, min);
- if (p < min) {
- p = min;
- }
-
- var max = imageSizeInImagePixels - viewportSizeInImagePixels / 2;
- max = Math.max (imageSizeInImagePixels / 2, max);
- if (p > max) {
- p = max;
- }
- return p;
- };
-
- var o = {};
- if (x != null) {
- o.x = constrain (viewportWidthInImagePixels, this.width, x);
- }
-
- if (y != null) {
- o.y = constrain (viewportHeightInImagePixels, this.height, y);
- }
-
- return o;
- },
-
- /**
- * Lays out all layers according to the current
- * x, y and zoom values.
- *
- * @public
- */
- layout : function () {
- var viewportWidth = this.container.clientWidth;
- var viewportHeight = this.container.clientHeight;
-
- var zoomWithStretch = Math.min (this.maxZoom, Math.max (this.zoom - this.getTextureStretch (), this.minZoom));
-
- var zoomLevel = Math.min (0, Math.ceil (zoomWithStretch));
- var zoomFactor = Math.pow (2, zoomLevel);
-
- var clamped = this.clampXY (this.x, this.y);
-
- if (!this.parameters.wrapY) {
- this.y = clamped.y;
- }
-
- if (!this.parameters.wrapX) {
- this.x = clamped.x;
- }
-
- var tileWidthInRealPixels = this.tileSize / zoomFactor;
-
- var fractionalZoomFactor = Math.pow (2, this.zoom - zoomLevel);
- var tileDisplayWidth = this.tileSize * fractionalZoomFactor;
-
- var widthInTiles = this.width / tileWidthInRealPixels;
- var heightInTiles = this.height / tileWidthInRealPixels;
- var centerInTilesX = this.x / tileWidthInRealPixels;
- var centerInTilesY = this.y / tileWidthInRealPixels;
-
- var topLeftInTilesX = centerInTilesX - (viewportWidth / 2) / tileDisplayWidth;
- var topLeftInTilesY = centerInTilesY - (viewportHeight / 2) / tileDisplayWidth;
-
- var topLeftTileX = Math.floor (topLeftInTilesX);
- var topLeftTileY = Math.floor (topLeftInTilesY);
- var topLeftTileXoffset = Math.round ((topLeftInTilesX - topLeftTileX) * tileDisplayWidth);
- var topLeftTileYoffset = Math.round ((topLeftInTilesY - topLeftTileY) * tileDisplayWidth);
-
- for (var i = 0; i < this.layers.length; ++i) {
- this.layers[i].layout (
- zoomWithStretch,
- -topLeftTileXoffset - tileDisplayWidth, -topLeftTileYoffset - tileDisplayWidth,
- topLeftTileX - 1, topLeftTileY - 1,
- Math.ceil (tileDisplayWidth), Math.ceil (tileDisplayWidth),
- 1.0);
- }
- },
-
- /**
- * Resizes the layers of this image.
- *
- * @public
- */
- resize : function () {
- var tilesW = Math.ceil (2 * this.container.clientWidth / this.tileSize) + 2;
- var tilesH = Math.ceil (2 * this.container.clientHeight / this.tileSize) + 2;
- for (var i = 0; i < this.layers.length; ++i) {
- this.layers[i].resize (tilesW, tilesH);
- }
- },
-
- /**
- * Creates a HTML div container for a layer. This method
- * is called by the layer's constructor to obtain a
- * container.
- *
- * @public
- * @type HTMLDivElement
- */
- createLayerContainer : function () {
- var layerContainer = document.createElement ("div");
- layerContainer.style.position = "absolute";
- layerContainer.style.overflow = "hidden";
- return layerContainer;
- },
-
- /**
- * Returns the div element used as viewport.
- *
- * @public
- * @type HTMLDivElement
- */
- getContainer : function () {
- return this.container;
- },
-
- /**
- * Adds a new layer to the image.
- *
- * @public
- * @see bigshot.HotspotLayer for usage example
- * @param {bigshot.Layer} layer the layer to add.
- */
- addLayer : function (layer) {
- this.container.appendChild (layer.getContainer ());
- this.layers.push (layer);
- },
-
- /**
- * Clamps the zoom value to be between minZoom and maxZoom.
- *
- * @param {number} zoom the zoom value
- * @type number
- */
- clampZoom : function (zoom) {
- return Math.min (this.maxZoom, Math.max (zoom, this.minZoom));
- },
-
- /**
- * Sets the current zoom value.
- *
- * @private
- * @param {number} zoom the zoom value.
- * @param {boolean} [layout] trigger a viewport update after setting. Defaults to <code>false</code>.
- */
- setZoom : function (zoom, updateViewport) {
- this.zoom = this.clampZoom (zoom);
- var zoomLevel = Math.ceil (this.zoom - this.getTextureStretch ());
- var zoomFactor = Math.pow (2, zoomLevel);
- var maxTileX = Math.ceil (zoomFactor * this.width / this.tileSize);
- var maxTileY = Math.ceil (zoomFactor * this.height / this.tileSize);
- for (var i = 0; i < this.layers.length; ++i) {
- this.layers[i].setMaxTiles (maxTileX, maxTileY);
- }
- if (updateViewport) {
- this.layout ();
- }
- },
-
- /**
- * Sets the maximum zoom value. The maximum magnification (of the full-size image)
- * is 2<sup>maxZoom</sup>. Set to 0.0 to avoid pixelation.
- *
- * @public
- * @param {number} maxZoom the maximum zoom value
- */
- setMaxZoom : function (maxZoom) {
- this.maxZoom = maxZoom;
- },
-
- /**
- * Gets the maximum zoom value. The maximum magnification (of the full-size image)
- * is 2<sup>maxZoom</sup>.
- *
- * @public
- * @type number
- */
- getMaxZoom : function () {
- return this.maxZoom;
- },
-
- /**
- * Sets the minimum zoom value. The minimum magnification (of the full-size image)
- * is 2<sup>minZoom</sup>, so a minZoom of <code>-3</code> means that the smallest
- * image shown will be one-eighth of the full-size image.
- *
- * @public
- * @param {number} minZoom the minimum zoom value for this image
- */
- setMinZoom : function (minZoom) {
- this.minZoom = minZoom;
- },
-
- /**
- * Gets the minimum zoom value. The minimum magnification (of the full-size image)
- * is 2<sup>minZoom</sup>, so a minZoom of <code>-3</code> means that the smallest
- * image shown will be one-eighth of the full-size image.
- *
- * @public
- * @type number
- */
- getMinZoom : function () {
- return this.minZoom;
- },
-
- /**
- * Adjusts a coordinate so that the center of zoom
- * remains constant during zooming operations. The
- * method is intended to be called twice, once for x
- * and once for y. The <code>current</code> and
- * <code>centerOfZoom</code> values will be the current
- * and the center for the x and y, respectively.
- *
- * @example
- * this.x = this.adjustCoordinateForZoom (this.x, zoomCenterX, oldZoom, newZoom);
- * this.y = this.adjustCoordinateForZoom (this.y, zoomCenterY, oldZoom, newZoom);
- *
- * @param {number} current the current value of the coordinate
- * @param {number} centerOfZoom the center of zoom along the coordinate axis
- * @param {number} oldZoom the old zoom value
- * @param {number} oldZoom the new zoom value
- * @type number
- * @returns the new value for the coordinate
- */
- adjustCoordinateForZoom : function (current, centerOfZoom, oldZoom, newZoom) {
- var zoomRatio = Math.pow (2, oldZoom) / Math.pow (2, newZoom);
- return centerOfZoom + (current - centerOfZoom) * zoomRatio;
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureStart : function (event) {
- this.currentGesture = {
- startZoom : this.zoom,
- scale : event.scale
- };
- },
-
- /**
- * Ends a gesture.
- *
- * @param {Event} event the <code>gestureend</code> event
- * @private
- */
- gestureEnd : function (event) {
- this.currentGesture = null;
- if (this.dragStart) {
- this.dragStart.hadGesture = true;
- }
- },
-
- /**
- * Adjusts the zoom level based on the scale property of the
- * gesture.
- *
- * @private
- */
- gestureChange : function (event) {
- if (this.currentGesture) {
- if (this.dragStart) {
- this.dragStart.hadGesture = true;
- }
-
- var newZoom = this.clampZoom (this.currentGesture.startZoom + Math.log (event.scale) / Math.log (2));
- var oldZoom = this.getZoom ();
- if (this.currentGesture.clientX !== undefined && this.currentGesture.clientY !== undefined) {
- var centerOfZoom = this.clientToImage (this.currentGesture.clientX, this.currentGesture.clientY);
-
- var nx = this.adjustCoordinateForZoom (this.x, centerOfZoom.x, oldZoom, newZoom);
- var ny = this.adjustCoordinateForZoom (this.y, centerOfZoom.y, oldZoom, newZoom);
-
- this.moveTo (nx, ny, newZoom);
- } else {
- this.setZoom (newZoom);
- this.layout ();
- }
- }
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- dragMouseDown : function (event) {
- this.dragStart = {
- x : event.clientX,
- y : event.clientY
- };
- this.dragLast = {
- clientX : event.clientX,
- clientY : event.clientY,
- dx : 0,
- dy : 0,
- dt : 1000000,
- time : new Date ().getTime ()
- };
- this.dragged = false;
- },
-
- /**
- * Handles a mouse drag event by panning the image.
- * Also sets the dragged flag to indicate that the
- * following <code>click</code> event should be ignored.
- * @private
- */
- dragMouseMove : function (event) {
- if (this.currentGesture != null && event.changedTouches != null && event.changedTouches.length > 0) {
- var cx = 0;
- var cy = 0;
- for (var i = 0; i < event.changedTouches.length; ++i) {
- cx += event.changedTouches[i].clientX;
- cy += event.changedTouches[i].clientY;
- }
- this.currentGesture.clientX = cx / event.changedTouches.length;
- this.currentGesture.clientY = cy / event.changedTouches.length;
- }
-
- if (this.currentGesture == null && this.dragStart != null) {
- var delta = {
- x : event.clientX - this.dragStart.x,
- y : event.clientY - this.dragStart.y
- };
- if (delta.x != 0 || delta.y != 0) {
- this.dragged = true;
- }
- var zoomFactor = Math.pow (2, this.zoom);
- var realX = delta.x / zoomFactor;
- var realY = delta.y / zoomFactor;
-
- this.dragStart = {
- x : event.clientX,
- y : event.clientY
- };
-
- var dt = new Date ().getTime () - this.dragLast.time;
- if (dt > 20) {
- this.dragLast = {
- dx : this.dragLast.clientX - event.clientX,
- dy : this.dragLast.clientY - event.clientY,
- dt : dt,
- clientX : event.clientX,
- clientY : event.clientY,
- time : new Date ().getTime ()
- };
- }
-
- this.moveTo (this.x - realX, this.y - realY);
- }
- },
-
- /**
- * Ends a drag event by freeing the associated structures.
- * @private
- */
- dragMouseUp : function (event) {
- if (this.currentGesture == null && !this.dragStart.hadGesture && this.dragStart != null) {
- this.dragStart = null;
- if (!this.dragged) {
- this.mouseClick (event);
- } else {
- var scale = Math.pow (2, this.zoom);
- var dx = this.dragLast.dx / scale;
- var dy = this.dragLast.dy / scale;
- var ds = Math.sqrt (dx * dx + dy * dy);
- var dt = this.dragLast.dt;
- var dtb = new Date ().getTime () - this.dragLast.time;
- this.dragLast = null;
-
- var v = dt > 0 ? (ds / dt) : 0;
- if (v > 0.05 && dtb < 250 && dt > 20 && this.parameters.fling) {
- var t0 = new Date ().getTime ();
-
- dx /= dt;
- dy /= dt;
-
- this.flyTo (this.x + dx * 250, this.y + dy * 250, this.zoom);
- }
- }
- }
- },
-
- /**
- * Mouse double-click handler. Pans to the clicked point and
- * zooms in half a zoom level (approx 40%).
- * @private
- */
- mouseDoubleClick : function (event) {
- var eventData = this.createImageEventData ({
- type : "dblclick",
- clientX : event.clientX,
- clientY : event.clientY
- });
- this.fireEvent ("dblclick", eventData);
- if (!eventData.defaultPrevented) {
- this.flyTo (eventData.imageX, eventData.imageY, this.zoom + 0.5);
- }
- },
-
- /**
- * Returns the current zoom level.
- *
- * @public
- * @type number
- */
- getZoom : function () {
- return this.zoom;
- },
-
- /**
- * Stops any current flyTo operation and sets the current position.
- *
- * @param [x] the new x-coordinate
- * @param [y] the new y-coordinate
- * @param [zoom] the new zoom level
- * @param [updateViewport=true] updates the viewport
- * @public
- */
- moveTo : function (x, y, zoom, updateViewport) {
- this.stopFlying ();
-
- if (x != null || y != null) {
- this.setPosition (x, y, false);
- }
- if (zoom != null) {
- this.setZoom (zoom, false);
- }
- if (updateViewport == undefined || updateViewport == true) {
- this.layout ();
- }
- },
-
- /**
- * Sets the current position.
- *
- * @param [x] the new x-coordinate
- * @param [y] the new y-coordinate
- * @param [updateViewport=true] if the viewport should be updated
- * @private
- */
- setPosition : function (x, y, updateViewport) {
- var clamped = this.clampXY (x, y);
-
- if (x != null) {
- if (this.parameters.wrapX) {
- if (x < 0 || x >= this.width) {
- x = (x + this.width) % this.width;
- }
- } else {
- x = clamped.x;
- }
- this.x = Math.max (0, Math.min (this.width, x));
- }
-
- if (y != null) {
- if (this.parameters.wrapY) {
- if (y < 0 || y >= this.height) {
- y = (y + this.height) % this.height;
- }
- } else {
- y = clamped.y;
- }
- this.y = Math.max (0, Math.min (this.height, y));
- }
-
- if (updateViewport != false) {
- this.layout ();
- }
- },
-
- /**
- * Helper function for calculating zoom levels.
- *
- * @public
- * @returns the zoom level at which the given number of full-image pixels
- * occupy the given number of screen pixels.
- * @param {number} imageDimension the image dimension in full-image pixels
- * @param {number} containerDimension the container dimension in screen pixels
- * @type number
- */
- fitZoom : function (imageDimension, containerDimension) {
- var scale = containerDimension / imageDimension;
- return Math.log (scale) / Math.LN2;
- },
-
- /**
- * Returns the maximum zoom level at which the full image
- * is visible in the viewport.
- * @public
- * @type number
- */
- getZoomToFitValue : function () {
- return Math.min (
- this.fitZoom (this.parameters.width, this.container.clientWidth),
- this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Returns the zoom level at which the image fills the whole
- * viewport.
- * @public
- * @type number
- */
- getZoomToFillValue : function () {
- return Math.max (
- this.fitZoom (this.parameters.width, this.container.clientWidth),
- this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Adjust the zoom level to fit the image in the viewport.
- * @public
- */
- zoomToFit : function () {
- this.moveTo (null, null, this.getZoomToFitValue ());
- },
-
- /**
- * Adjust the zoom level to fit the image in the viewport.
- * @public
- */
- zoomToFill : function () {
- this.moveTo (null, null, this.getZoomToFillValue ());
- },
-
- /**
- * Adjust the zoom level to fit the
- * image height in the viewport.
- * @public
- */
- zoomToFitHeight : function () {
- this.moveTo (null, null, this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Adjust the zoom level to fit the
- * image width in the viewport.
- * @public
- */
- zoomToFitWidth : function () {
- this.moveTo (null, null, this.fitZoom (this.parameters.width, this.container.clientWidth));
- },
-
- /**
- * Smoothly adjust the zoom level to fit the
- * image height in the viewport.
- * @public
- */
- flyZoomToFitHeight : function () {
- this.flyTo (null, this.parameters.height / 2, this.fitZoom (this.parameters.height, this.container.clientHeight));
- },
-
- /**
- * Smoothly adjust the zoom level to fit the
- * image width in the viewport.
- * @public
- */
- flyZoomToFitWidth : function () {
- this.flyTo (this.parameters.width / 2, null, this.fitZoom (this.parameters.width, this.container.clientWidth));
- },
-
- /**
- * Smoothly adjust the zoom level to fit the
- * full image in the viewport.
- * @public
- */
- flyZoomToFit : function () {
- this.flyTo (this.parameters.width / 2, this.parameters.height / 2, this.getZoomToFitValue ());
- },
-
- /**
- * Converts client-relative screen coordinates to image coordinates.
- *
- * @param {number} clientX the client x-coordinate
- * @param {number} clientY the client y-coordinate
- *
- * @returns {number} .x the image x-coordinate
- * @returns {number} .y the image y-coordinate
- * @type Object
- */
- clientToImage : function (clientX, clientY) {
- var zoomFactor = Math.pow (2, this.zoom);
- return {
- x : (clientX - this.container.clientWidth / 2) / zoomFactor + this.x,
- y : (clientY - this.container.clientHeight / 2) / zoomFactor + this.y
- };
- },
-
- /**
- * Handles mouse wheel actions.
- * @private
- */
- mouseWheelHandler : function (delta, event) {
- var zoomDelta = false;
- if (delta > 0) {
- zoomDelta = 0.5;
- } else if (delta < 0) {
- zoomDelta = -0.5;
- }
-
- if (zoomDelta) {
- var centerOfZoom = this.clientToImage (event.clientX, event.clientY);
- var newZoom = Math.min (this.maxZoom, Math.max (this.getZoom () + zoomDelta, this.minZoom));
-
- var nx = this.adjustCoordinateForZoom (this.x, centerOfZoom.x, this.getZoom (), newZoom);
- var ny = this.adjustCoordinateForZoom (this.y, centerOfZoom.y, this.getZoom (), newZoom);
-
- this.flyTo (nx, ny, newZoom, true);
- }
- },
-
- /**
- * Translates mouse wheel events.
- * @private
- */
- mouseWheel : function (event){
- var delta = 0;
- if (!event) /* For IE. */
- event = window.event;
- if (event.wheelDelta) { /* IE/Opera. */
- delta = event.wheelDelta / 120;
- /*
- * In Opera 9, delta differs in sign as compared to IE.
- */
- if (window.opera)
- delta = -delta;
- } else if (event.detail) { /* Mozilla case. */
- /*
- * In Mozilla, sign of delta is different than in IE.
- * Also, delta is multiple of 3.
- */
- delta = -event.detail;
- }
-
- /*
- * If delta is nonzero, handle it.
- * Basically, delta is now positive if wheel was scrolled up,
- * and negative, if wheel was scrolled down.
- */
- if (delta) {
- this.mouseWheelHandler (delta, event);
- }
-
- /*
- * Prevent default actions caused by mouse wheel.
- * That might be ugly, but we handle scrolls somehow
- * anyway, so don't bother here..
- */
- if (event.preventDefault) {
- event.preventDefault ();
- }
- event.returnValue = false;
- },
-
- /**
- * Triggers a right-sizing of all layers.
- * Called on window resize via the {@link bigshot.ImageBase#onresizeHandler} stub.
- * @public
- */
- onresize : function () {
- this.resize ();
- this.layout ();
- },
-
- /**
- * Returns the current x-coordinate, which is the full-image x coordinate
- * in the center of the viewport.
- * @public
- * @type number
- */
- getX : function () {
- return this.x;
- },
-
- /**
- * Returns the current y-coordinate, which is the full-image x coordinate
- * in the center of the viewport.
- * @public
- * @type number
- */
- getY : function () {
- return this.y;
- },
-
- /**
- * Interrupts the current {@link #flyTo}, if one is active.
- * @public
- */
- stopFlying : function () {
- this.flying++;
- },
-
- /**
- * Smoothly flies to the specified position.
- *
- * @public
- * @param {number} [x=current x] the new x-coordinate
- * @param {number} [y=current y] the new y-coordinate
- * @param {number} [zoom=current zoom] the new zoom level
- * @param {boolean} [uniformApproach=false] if true, uses the same interpolation curve for x, y and zoom.
- */
- flyTo : function (x, y, zoom, uniformApproach) {
- var that = this;
-
- x = x != null ? x : this.x;
- y = y != null ? y : this.y;
- zoom = zoom != null ? zoom : this.zoom;
- uniformApproach = uniformApproach != null ? uniformApproach : false;
-
- var startX = this.x;
- var startY = this.y;
- var startZoom = this.zoom;
-
- var clamped = this.clampXY (x, y);
- var targetX = this.parameters.wrapX ? x : clamped.x;
- var targetY = this.parameters.wrapY ? y : clamped.y;
- var targetZoom = Math.min (this.maxZoom, Math.max (zoom, this.minZoom));
-
- this.flying++;
- var flyingAtStart = this.flying;
-
- var t0 = new Date ().getTime ();
-
- var approach = function (start, target, dt, step, linear) {
- var delta = (target - start);
-
- var diff = - delta * Math.pow (2, -dt * step);
-
- var lin = dt * linear;
- if (delta < 0) {
- diff = Math.max (0, diff - lin);
- } else {
- diff = Math.min (0, diff + lin);
- }
-
- return target + diff;
- };
-
-
- var iter = function () {
- if (that.flying == flyingAtStart) {
- var dt = (new Date ().getTime () - t0) / 1000;
-
- var nx = approach (startX, targetX, dt, uniformApproach ? 10 : 4, uniformApproach ? 0.2 : 1.0);
- var ny = approach (startY, targetY, dt, uniformApproach ? 10 : 4, uniformApproach ? 0.2 : 1.0);
- var nz = approach (startZoom, targetZoom, dt, 10, 0.2);
- var done = true;
-
- var zoomFactor = Math.min (Math.pow (2, that.getZoom ()), 1);
-
- if (Math.abs (nx - targetX) < (0.5 * zoomFactor)) {
- nx = targetX;
- } else {
- done = false;
- }
- if (Math.abs (ny - targetY) < (0.5 * zoomFactor)) {
- ny = targetY;
- } else {
- done = false;
- }
- if (Math.abs (nz - targetZoom) < 0.02) {
- nz = targetZoom;
- } else {
- done = false;
- }
- that.setPosition (nx, ny, false);
- that.setZoom (nz, false);
- that.layout ();
- if (!done) {
- that.browser.requestAnimationFrame (iter, that.container);
- }
- };
- }
- this.browser.requestAnimationFrame (iter, this.container);
- },
-
- /**
- * Returns the maximum zoom level at which a rectangle with the given dimensions
- * fit into the viewport.
- *
- * @public
- * @param {number} w the width of the rectangle, given in full-image pixels
- * @param {number} h the height of the rectangle, given in full-image pixels
- * @type number
- * @returns the zoom level that will precisely fit the given rectangle
- */
- rectVisibleAtZoomLevel : function (w, h) {
- return Math.min (
- this.fitZoom (w, this.container.clientWidth),
- this.fitZoom (h, this.container.clientHeight));
- },
-
- /**
- * Returns the base size in screen pixels of the two zoom touch areas.
- * The zoom out border will be getTouchAreaBaseSize() pixels wide,
- * and the center zoom in hotspot will be 2*getTouchAreaBaseSize() pixels wide
- * and tall.
- * @deprecated
- * @type number
- * @public
- */
- getTouchAreaBaseSize : function () {
- var averageSize = ((this.container.clientWidth + this.container.clientHeight) / 2) * 0.2;
- return Math.min (averageSize, Math.min (this.container.clientWidth, this.container.clientHeight) / 6);
- },
-
- /**
- * Creates a new {@link bigshot.ImageEvent} using the supplied data object,
- * transforming the client x- and y-coordinates to local and image coordinates.
- * The returned event object will have the {@link bigshot.ImageEvent#localX},
- * {@link bigshot.ImageEvent#localY}, {@link bigshot.ImageEvent#imageX},
- * {@link bigshot.ImageEvent#imageY}, {@link bigshot.Event#target} and
- * {@link bigshot.Event#currentTarget} fields set.
- *
- * @param {Object} data data object with initial values for the event object
- * @param {number} data.clientX the clientX of the event
- * @param {number} data.clientY the clientY of the event
- * @returns the new event object
- * @type bigshot.ImageEvent
- */
- createImageEventData : function (data) {
- var elementPos = this.browser.getElementPosition (this.container);
- data.localX = data.clientX - elementPos.x;
- data.localY = data.clientY - elementPos.y;
-
- var scale = Math.pow (2, this.zoom);
-
- data.imageX = (data.localX - this.container.clientWidth / 2) / scale + this.x;
- data.imageY = (data.localY - this.container.clientHeight / 2) / scale + this.y;
-
- data.target = this;
- data.currentTarget = this;
-
- return new bigshot.ImageEvent (data);
- },
-
- /**
- * Handles mouse click events. If the touch UI is active,
- * we'll pan and/or zoom, as appropriate. If not, we just ignore
- * the event.
- * @private
- */
- mouseClick : function (event) {
- var eventData = this.createImageEventData ({
- type : "click",
- clientX : event.clientX,
- clientY : event.clientY
- });
- this.fireEvent ("click", eventData);
- /*
- if (!eventData.defaultPrevented) {
- if (!this.parameters.touchUI) {
- return;
- }
- if (this.dragged) {
- return;
- }
-
- var zoomOutBorderSize = this.getTouchAreaBaseSize ();
- var zoomInHotspotSize = this.getTouchAreaBaseSize ();
-
- if (Math.abs (clickPos.x) > (this.container.clientWidth / 2 - zoomOutBorderSize) || Math.abs (clickPos.y) > (this.container.clientHeight / 2 - zoomOutBorderSize)) {
- this.flyTo (this.x, this.y, this.zoom - 0.5);
- } else {
- var newZoom = this.zoom;
- if (Math.abs (clickPos.x) < zoomInHotspotSize && Math.abs (clickPos.y) < zoomInHotspotSize) {
- newZoom += 0.5;
- }
- var scale = Math.pow (2, this.zoom);
- clickPos.x /= scale;
- clickPos.y /= scale;
- this.flyTo (this.x + clickPos.x, this.y + clickPos.y, newZoom);
- }
- }
- */
- },
-
- /**
- * Briefly shows the touch ui zones. See the {@link bigshot.ImageParameters#touchUI}
- * documentation for an explanation of the touch ui.
- *
- * @public
- * @deprecated All common touch gestures are supported by default.
- * @see bigshot.ImageParameters#touchUI
- * @param {int} [delay] milliseconds before fading out
- * @param {int} [fadeOut] milliseconds to fade out the zone overlays in
- */
- showTouchUI : function (delay, fadeOut) {
- if (!delay) {
- delay = 2500;
- }
- if (!fadeOut) {
- fadeOut = 1000;
- }
-
- var zoomOutBorderSize = this.getTouchAreaBaseSize ();
- var zoomInHotspotSize = this.getTouchAreaBaseSize ();
- var centerX = this.container.clientWidth / 2;
- var centerY = this.container.clientHeight / 2;
-
- var frameDiv = document.createElement ("div");
- frameDiv.style.position = "absolute";
- frameDiv.style.zIndex = "9999";
- frameDiv.style.opacity = 0.9;
- frameDiv.style.width = this.container.clientWidth + "px";
- frameDiv.style.height = this.container.clientHeight + "px";
-
- var centerSpotAnchor = document.createElement ("div");
- centerSpotAnchor.style.position = "absolute";
-
- var centerSpot = document.createElement ("div");
- centerSpot.style.position = "relative";
- centerSpot.style.background = "black";
- centerSpot.style.textAlign = "center";
- centerSpot.style.top = (centerY - zoomInHotspotSize) + "px";
- centerSpot.style.left = (centerX - zoomInHotspotSize) + "px";
- centerSpot.style.width = (2 * zoomInHotspotSize) + "px";
- centerSpot.style.height = (2 * zoomInHotspotSize) + "px";
-
- frameDiv.appendChild (centerSpotAnchor);
- centerSpotAnchor.appendChild (centerSpot);
- centerSpot.innerHTML = "<span style='display:inline-box; position:relative; vertical-align:middle; font-size: 20pt; top: 10pt; color:white'>ZOOM IN</span>";
-
- var zoomOutBorderAnchor = document.createElement ("div");
- zoomOutBorderAnchor.style.position = "absolute";
-
- var zoomOutBorder = document.createElement ("div");
- zoomOutBorder.style.position = "relative";
- zoomOutBorder.style.border = zoomOutBorderSize + "px solid black";
- zoomOutBorder.style.top = "0px";
- zoomOutBorder.style.left = "0px";
- zoomOutBorder.style.textAlign = "center";
- zoomOutBorder.style.width = this.container.clientWidth + "px";
- zoomOutBorder.style.height = this.container.clientHeight + "px";
- zoomOutBorder.style.MozBoxSizing =
- zoomOutBorder.style.boxSizing =
- zoomOutBorder.style.WebkitBoxSizing =
- "border-box";
-
- zoomOutBorder.innerHTML = "<span style='position:relative; font-size: 20pt; top: -25pt; color:white'>ZOOM OUT</span>";
-
- zoomOutBorderAnchor.appendChild (zoomOutBorder);
- frameDiv.appendChild (zoomOutBorderAnchor);
-
- this.container.appendChild (frameDiv);
-
- var that = this;
- var opacity = 0.9;
- var fadeOutSteps = fadeOut / 50;
- if (fadeOutSteps < 1) {
- fadeOutSteps = 1;
- }
- var iter = function () {
- opacity = opacity - (0.9 / fadeOutSteps);
- if (opacity < 0.0) {
- that.container.removeChild (frameDiv);
- } else {
- frameDiv.style.opacity = opacity;
- setTimeout (iter, 50);
- }
- };
- setTimeout (iter, delay);
- },
-
- /**
- * Forces exit from full screen mode, if we're there.
- * @public
- */
- exitFullScreen : function () {
- if (this.fullScreenHandler) {
- this.removeEventListeners ();
- this.fullScreenHandler.close ();
- this.addEventListeners ();
- this.fullScreenHandler = null;
- return;
- }
- },
-
- /**
- * Maximizes the image to cover the browser viewport.
- * The container div is removed from its parent node upon entering
- * full screen mode. When leaving full screen mode, the container
- * is appended to its old parent node. To avoid rearranging the
- * nodes, wrap the container in an extra div.
- *
- * <p>For unknown reasons (probably security), browsers will
- * not let you open a window that covers the entire screen.
- * Even when specifying "fullscreen=yes", all you get is a window
- * that has a title bar and only covers the desktop (not any task
- * bars or the like). For now, this is the best that I can do,
- * but should the situation change I'll update this to be
- * full-screen<i>-ier</i>.
- * @public
- */
- fullScreen : function (onClose) {
- if (this.fullScreenHandler) {
- return;
- }
-
- var message = document.createElement ("div");
- message.style.position = "absolute";
- message.style.fontSize = "16pt";
- message.style.top = "128px";
- message.style.width = "100%";
- message.style.color = "white";
- message.style.padding = "16px";
- message.style.zIndex = "9999";
- message.style.textAlign = "center";
- message.style.opacity = "0.75";
- message.innerHTML = "<span style='border-radius: 16px; -moz-border-radius: 16px; padding: 16px; padding-left: 32px; padding-right: 32px; background:black'>Press Esc to exit full screen mode.</span>";
-
- var that = this;
-
- this.fullScreenHandler = new bigshot.FullScreen (this.container);
- this.fullScreenHandler.restoreSize = true;
-
- this.fullScreenHandler.addOnResize (function () {
- if (that.fullScreenHandler && that.fullScreenHandler.isFullScreen) {
- that.container.style.width = window.innerWidth + "px";
- that.container.style.height = window.innerHeight + "px";
- }
- that.onresize ();
- });
-
- this.fullScreenHandler.addOnClose (function () {
- if (message.parentNode) {
- try {
- div.removeChild (message);
- } catch (x) {
- }
- }
- that.fullScreenHandler = null;
- });
-
- if (onClose) {
- this.fullScreenHandler.addOnClose (function () {
- onClose ();
- });
- }
-
- this.removeEventListeners ();
- this.fullScreenHandler.open ();
- this.addEventListeners ();
- if (this.fullScreenHandler.getRootElement ()) {
- this.fullScreenHandler.getRootElement ().appendChild (message);
-
- setTimeout (function () {
- var opacity = 0.75;
- var iter = function () {
- opacity -= 0.02;
- if (message.parentNode) {
- if (opacity <= 0) {
- try {
- div.removeChild (message);
- } catch (x) {}
- } else {
- message.style.opacity = opacity;
- setTimeout (iter, 20);
- }
- }
- };
- setTimeout (iter, 20);
- }, 3500);
- }
-
- return function () {
- that.fullScreenHandler.close ();
- };
- },
-
- /**
- * Unregisters event handlers and other page-level hooks. The client need not call this
- * method unless bigshot images are created and removed from the page
- * dynamically. In that case, this method must be called when the client wishes to
- * free the resources allocated by the image. Otherwise the browser will garbage-collect
- * all resources automatically.
- * @public
- */
- dispose : function () {
- this.browser.unregisterListener (window, "resize", this.onresizeHandler, false);
- this.removeEventListeners ();
- }
-};
-
-/**
- * Fired when the user double-clicks on the image
- *
- * @name bigshot.ImageBase#dblclick
- * @event
- * @param {bigshot.ImageEvent} event the event object
- */
-
-/**
- * Fired when the user clicks on (but does not drag) the image
- *
- * @name bigshot.ImageBase#click
- * @event
- * @param {bigshot.ImageEvent} event the event object
- */
-
-bigshot.Object.extend (bigshot.ImageBase, bigshot.EventDispatcher);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * Creates a new tiled image viewer. (Note: See {@link bigshot.ImageBase#dispose} for important information.)
- *
- * @example
- * var bsi = new bigshot.Image (
- * new bigshot.ImageParameters ({
- * basePath : "/bigshot.php?file=myshot.bigshot",
- * fileSystemType : "archive",
- * container : document.getElementById ("bigshot_div")
- * }));
- *
- * @param {bigshot.ImageParameters} parameters the image parameters. Required fields are: <code>basePath</code> and <code>container</code>.
- * If you intend to use the archive filesystem, you need to set the <code>fileSystemType</code> to <code>"archive"</code>
- * as well.
- * @see bigshot.ImageBase#dispose
- * @class A tiled, zoomable image viewer.
- *
- * <h3 id="creating-a-wrapping-image">Creating a Wrapping Image</h3>
- *
- * <p>If you have set the wrapX or wrapY parameters in the {@link bigshot.ImageParameters}, the
- * image must be an integer multiple of the tile size at the desired minimum zoom level, otherwise
- * there will be a gap at the wrap point:
- *
- * <p>The way to figure out the proper input size is this:
- *
- * <ol>
- * <li><p>Decide on a tile size and call this <i>tileSize</i>.</p></li>
- * <li><p>Decide on a minimum integer zoom level, and call this <i>minZoom</i>.</p></li>
- * <li><p>Compute <i>tileSize * 2<sup>-minZoom</sup></i>, call this <i>S</i>.</p></li>
- * <li><p>The source image size along the wrapped axis must be evenly divisible by <i>S</i>.</p></li>
- * </ol>
- *
- * <p>An example:</p>
- *
- * <ol>
- * <li><p>I have an image that is 23148x3242 pixels.</p></li>
- * <li><p>I chose 256x256 pixel tiles: <i>tileSize = 256</i>.</p></li>
- * <li><p>When displaying the image, I want the user to be able to zoom out so that the
- * whole image is less than or equal to 600 pixels tall. Since the image is 3242 pixels
- * tall originally, I will need a <i>minZoom</i> of -3. A <i>minZoom</i> of -2 would only let me
- * zoom out to 1/4 (2<sup>-2</sup>), or an image that is 810 pixels tall. A <i>minZoom</i> of -3, however lets me
- * zoom out to 1/8 (2<sup>-3</sup>), or an image that is 405 pixels tall. Thus: <i>minZoom = -3</i></p></li>
- * <li><p>Computing <i>S</i> gives: <i>S = 256 * 2<sup>3</sup> = 256 * 8 = 2048</i></p></li>
- * <li><p>I want it to wrap along the X axis. Therefore I may have to adjust the width,
- * currently 23148 pixels.</p></li>
- * <li><p>Rounding 23148 down to the nearest multiple of 2048 gives 22528. (23148 divided by 2048 is 11.3, and 11 times 2048 is 22528.)</p></li>
- * <li><p>I will shrink my source image to be 22528 pixels wide before building the image pyramid,
- * and I will set the <code>minZoom</code> parameter to -3 in the {@link bigshot.ImageParameters} when creating
- * the image. (I will also set <code>wrapX</code> to <code>true</code>.)</p></li>
- * </ol>
- *
- * @augments bigshot.ImageBase
- */
-bigshot.Image = function (parameters) {
- bigshot.setupFileSystem (parameters);
- parameters.merge (parameters.fileSystem.getDescriptor (), false);
-
- bigshot.ImageBase.call (this, parameters);
-}
-
-bigshot.Image.prototype = {
- setupLayers : function () {
- var that = this;
- this.thisTileCache = new bigshot.ImageTileCache (function () {
- that.layout ();
- }, null, this.parameters);
-
- this.addLayer (
- new bigshot.TileLayer (this, this.parameters, 0, 0, this.thisTileCache)
- );
- }
-};
-
-bigshot.Object.extend (bigshot.Image, bigshot.ImageBase);
-
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new HTML element layer. The layer must be added to the image using
- * {@link bigshot.ImageBase#addLayer}.
- *
- * @class A layer consisting of a single HTML element that is moved and scaled to cover
- * the layer.
- * @example
- * var image = new bigshot.Image (...);
- * image.addLayer (
- * new bigshot.HTMLElementLayer (this, this.imgElement, this.parameters.width, this.parameters.height)
- * );
- * @param {bigshot.ImageBase} image the image this hotspot layer will be part of
- * @param {HTMLElement} element the element to present in this layer
- * @param {int} width the width, in image pixels (display size at zoom level 0), of the HTML element
- * @param {int} height the height, in image pixels (display size at zoom level 0), of the HTML element
- * @augments bigshot.Layer
- */
-bigshot.HTMLElementLayer = function (image, element, width, height) {
- this.hotspots = new Array ();
- this.browser = new bigshot.Browser ();
- this.image = image;
- this.container = image.createLayerContainer ();
- this.parentContainer = image.getContainer ();
- this.element = element;
- this.parentContainer.appendChild (element);
- this.w = width;
- this.h = height;
- this.resize (0, 0);
-}
-
-bigshot.HTMLElementLayer.prototype = {
-
- getContainer : function () {
- return this.container;
- },
-
- resize : function (w, h) {
- this.container.style.width = this.parentContainer.clientWidth + "px";
- this.container.style.height = this.parentContainer.clientHeight + "px";
- },
-
- layout : function (zoom, x0, y0, tx0, ty0, size, stride, opacity) {
- var zoomFactor = Math.pow (2, this.image.getZoom ());
- x0 -= stride * tx0;
- y0 -= stride * ty0;
-
- this.element.style.top = y0 + "px";
- this.element.style.left = x0 + "px";
- this.element.style.width = (this.w * zoomFactor) + "px";
- this.element.style.height = (this.h * zoomFactor) + "px";
- },
-
- setMaxTiles : function (mtx, mty) {
- }
-}
-
-bigshot.Object.validate ("bigshot.HTMLElementLayer", bigshot.Layer);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new HTML element layer. The layer must be added to the image using
- * {@link bigshot.ImageBase#addLayer}.
- *
- * @class A layer consisting of a single HTML element that is moved and scaled to cover
- * the layer.
- * @example
- * var image = new bigshot.Image (...);
- * image.addLayer (
- * new bigshot.HTMLElementLayer (this, this.imgElement, this.parameters.width, this.parameters.height)
- * );
- * @param {bigshot.ImageBase} image the image this hotspot layer will be part of
- * @param {HTMLElement} element the element to present in this layer
- * @param {int} width the width, in image pixels (display size at zoom level 0), of the HTML element
- * @param {int} height the height, in image pixels (display size at zoom level 0), of the HTML element
- * @augments bigshot.Layer
- */
-bigshot.HTMLDivElementLayer = function (image, element, width, height, wrapX, wrapY) {
- this.wrapX = wrapX;
- this.wrapY = wrapY;
- this.hotspots = new Array ();
- this.browser = new bigshot.Browser ();
- this.image = image;
- this.container = image.createLayerContainer ();
- this.parentContainer = image.getContainer ();
- this.element = element;
- this.parentContainer.appendChild (element);
- this.w = width;
- this.h = height;
- this.resize (0, 0);
-}
-
-bigshot.HTMLDivElementLayer.prototype = {
-
- getContainer : function () {
- return this.container;
- },
-
- resize : function (w, h) {
- this.container.style.width = this.parentContainer.clientWidth + "px";
- this.container.style.height = this.parentContainer.clientHeight + "px";
- },
-
- layout : function (zoom, x0, y0, tx0, ty0, size, stride, opacity) {
- var zoomFactor = Math.pow (2, this.image.getZoom ());
- x0 -= stride * tx0;
- y0 -= stride * ty0;
-
- var imW = (this.w * zoomFactor);
- var imH = (this.h * zoomFactor);
-
- this.element.style.backgroundSize = imW + "px " + imH + "px";
-
- var bposX = "0px";
- var bposY = "0px";
-
- if (this.wrapY) {
- this.element.style.top = "0px";
- this.element.style.height = (this.parentContainer.clientHeight) + "px";
- bposY = y0 + "px";
- } else {
- this.element.style.top = y0 + "px";
- this.element.style.height = imH + "px";
- }
-
- if (this.wrapX) {
- this.element.style.left = "0px";
- this.element.style.width = (this.parentContainer.clientWidth) + "px";
- bposX = x0 + "px";
- } else {
- this.element.style.left = x0 + "px";
- this.element.style.width = imW + "px";
- }
-
- this.element.style.backgroundPosition = bposX + " " + bposY;
- },
-
- setMaxTiles : function (mtx, mty) {
- }
-}
-
-bigshot.Object.validate ("bigshot.HTMLDivElementLayer", bigshot.Layer);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-/**
- * Creates a new image viewer. (Note: See {@link bigshot.SimpleImage#dispose} for important information.)
- *
- * @example
- * var bsi = new bigshot.SimpleImage (
- * new bigshot.ImageParameters ({
- * basePath : "myimage.jpg",
- * width : 681,
- * height : 1024,
- * container : document.getElementById ("bigshot_div")
- * }));
- *
- * @param {bigshot.ImageParameters} parameters the image parameters. Required fields are: <code>container</code>.
- * If the <code>imgElement</code> parameter is not given, then <code>basePath</code>, <code>width</code> and <code>height</code> are also required. The
- * following parameters are not supported and should be left as defaults: <code>fileSystem</code>, <code>fileSystemType</code>,
- * <code>maxTextureMagnification</code> and <code>tileSize</code>. <code>wrapX</code> and <code>wrapY</code> may only be used if the imgElement is <b>not</b>
- * set.
- *
- * @param {HTMLImageElement} [imgElement] an img element to use. The element should have <code>style.position = "absolute"</code>.
- * @see bigshot.ImageBase#dispose
- * @class A zoomable image viewer.
- * @augments bigshot.ImageBase
- */
-bigshot.SimpleImage = function (parameters, imgElement) {
- parameters.merge ({
- fileSystem : null,
- fileSystemType : "simple",
- maxTextureMagnification : 1.0,
- tileSize : 1024
- }, true);
-
- if (imgElement) {
- parameters.merge ({
- width : imgElement.width,
- height : imgElement.height
- });
- this.imgElement = imgElement;
- } else {
- if (parameters.width == 0 || parameters.height == 0) {
- throw new Error ("No imgElement and missing width or height in ImageParameters");
- }
- }
- bigshot.setupFileSystem (parameters);
-
- bigshot.ImageBase.call (this, parameters);
-}
-
-bigshot.SimpleImage.prototype = {
- setupLayers : function () {
- if (!this.imgElement) {
- /*
- this.imgElement = document.createElement ("img");
- this.imgElement.src = this.parameters.basePath;
- this.imgElement.style.position = "absolute";
- */
- this.imgElement = document.createElement ("div");
- this.imgElement.style.backgroundImage = "url('" + this.parameters.basePath + "')";
- this.imgElement.style.position = "absolute";
- if (!this.parameters.wrapX && !this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "no-repeat";
- } else if (this.parameters.wrapX && !this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "repeat-x";
- } else if (!this.parameters.wrapX && this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "repeat-y";
- } else if (this.parameters.wrapX && this.parameters.wrapY) {
- this.imgElement.style.backgroundRepeat = "repeat";
- }
- }
-
- this.addLayer (
- new bigshot.HTMLDivElementLayer (this, this.imgElement, this.parameters.width, this.parameters.height, this.parameters.wrapX, this.parameters.wrapY)
- );
- }
-};
-
-bigshot.Object.extend (bigshot.SimpleImage, bigshot.ImageBase);
-
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Abstract filesystem definition.
- *
- * @class Abstract filesystem definition.
- */
-bigshot.FileSystem = function () {
-}
-
-bigshot.FileSystem.prototype = {
- /**
- * Returns the URL filename for the given filesystem entry.
- *
- * @param {String} name the entry name
- */
- getFilename : function (name) {},
-
- /**
- * Returns the entry filename for the given tile.
- *
- * @param {int} tileX the column of the tile
- * @param {int} tileY the row of the tile
- * @param {int} zoomLevel the zoom level
- */
- getImageFilename : function (tileX, tileY, zoomLevel) {},
-
- /**
- * Sets an optional prefix that is prepended, along with a forward
- * slash ("/"), to all names.
- *
- * @param {String} prefix the prefix
- */
- setPrefix : function (prefix) {},
-
- /**
- * Returns an image descriptor object from the descriptor file.
- *
- * @return a descriptor object
- */
- getDescriptor : function () {},
-
- /**
- * Returns the poster URL filename. For Bigshot images this is
- * typically the URL corresponding to the entry "poster.jpg",
- * but for other filesystems it can be different.
- */
- getPosterFilename : function () {}
-};
-
-/**
- * Sets up a filesystem instance in the given parameters object, if none exist.
- * If the {@link bigshot.ImageParameters#fileSystem} member isn't set, the
- * {@link bigshot.ImageParameters#fileSystemType} member is used to create a new
- * {@link bigshot.FileSystem} instance and set it.
- *
- * @param {bigshot.ImageParameters or bigshot.VRPanoramaParameters or bigshot.ImageCarouselPanoramaParameters} parameters the parameters object to populate
- */
-bigshot.setupFileSystem = function (parameters) {
- if (!parameters.fileSystem) {
- if (parameters.fileSystemType == "archive") {
- parameters.fileSystem = new bigshot.ArchiveFileSystem (parameters);
- } else if (parameters.fileSystemType == "dzi") {
- parameters.fileSystem = new bigshot.DeepZoomImageFileSystem (parameters);
- } else if (parameters.fileSystemType == "simple") {
- parameters.fileSystem = new bigshot.SimpleFileSystem (parameters);
- } else {
- parameters.fileSystem = new bigshot.FolderFileSystem (parameters);
- }
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new instance of a filesystem adapter for the SimpleImage class.
- *
- * @class Filesystem adapter for bigshot.SimpleImage. This class is not
- * supposed to be used outside of the {@link bigshot.SimpleImage} class.
- * @param {bigshot.ImageParameters} parameters the associated image parameters
- * @augments bigshot.FileSystem
- * @see bigshot.SimpleImage
- */
-bigshot.SimpleFileSystem = function (parameters) {
- this.parameters = parameters;
-};
-
-
-bigshot.SimpleFileSystem.prototype = {
- getDescriptor : function () {
- return {};
- },
-
- getPosterFilename : function () {
- return null;
- },
-
- getFilename : function (name) {
- return null;
- },
-
- getImageFilename : function (tileX, tileY, zoomLevel) {
- return null;
- },
-
- getPrefix : function () {
- return "";
- },
-
- setPrefix : function (prefix) {
- this.prefix = prefix;
- }
-}
-
-bigshot.Object.validate ("bigshot.SimpleFileSystem", bigshot.FileSystem);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new instance of a folder-based filesystem adapter.
- *
- * @augments bigshot.FileSystem
- * @class Folder-based filesystem.
- * @param {bigshot.ImageParameters|bigshot.VRPanoramaParameters} parameters the associated image parameters
- * @constructor
- */
-bigshot.FolderFileSystem = function (parameters) {
- this.prefix = null;
- this.suffix = "";
- this.parameters = parameters;
-}
-
-
-bigshot.FolderFileSystem.prototype = {
- getDescriptor : function () {
- this.browser = new bigshot.Browser ();
- var req = this.browser.createXMLHttpRequest ();
-
- req.open("GET", this.getFilename ("descriptor"), false);
- req.send(null);
- var descriptor = {};
- if(req.status == 200) {
- var substrings = req.responseText.split (":");
- for (var i = 0; i < substrings.length; i += 2) {
- if (substrings[i] == "suffix") {
- descriptor[substrings[i]] = substrings[i + 1];
- } else {
- descriptor[substrings[i]] = parseInt (substrings[i + 1]);
- }
- }
- this.suffix = descriptor.suffix;
- return descriptor;
- } else {
- throw new Error ("Unable to find descriptor.");
- }
- },
-
- getPosterFilename : function () {
- return this.getFilename ("poster" + this.suffix);
- },
-
- setPrefix : function (prefix) {
- this.prefix = prefix;
- },
-
- getPrefix : function () {
- if (this.prefix) {
- return this.prefix + "/";
- } else {
- return "";
- }
- },
-
- getFilename : function (name) {
- return this.parameters.basePath + "/" + this.getPrefix () + name;
- },
-
- getImageFilename : function (tileX, tileY, zoomLevel) {
- var key = (-zoomLevel) + "/" + tileX + "_" + tileY + this.suffix;
- return this.getFilename (key);
- }
-};
-
-bigshot.Object.validate ("bigshot.FolderFileSystem", bigshot.FileSystem);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new instance of a Deep Zoom Image folder-based filesystem adapter.
- *
- * @augments bigshot.FileSystem
- * @class A Deep Zoom Image filesystem.
- * @param {bigshot.ImageParameters|bigshot.VRPanoramaParameters} parameters the associated image parameters
- * @constructor
- */
-bigshot.DeepZoomImageFileSystem = function (parameters) {
- this.prefix = "";
- this.suffix = "";
-
- this.DZ_NAMESPACE = "http://schemas.microsoft.com/deepzoom/2009";
- this.fullZoomLevel = 0;
- this.posterName = "";
- this.parameters = parameters;
-}
-
-bigshot.DeepZoomImageFileSystem.prototype = {
- getDescriptor : function () {
- var descriptor = {};
-
- var xml = this.parameters.dataLoader.loadXml (this.parameters.basePath + this.prefix + ".xml", false);
- var image = xml.getElementsByTagName ("Image")[0];
- var size = xml.getElementsByTagName ("Size")[0];
- descriptor.width = parseInt (size.getAttribute ("Width"));
- descriptor.height = parseInt (size.getAttribute ("Height"));
- descriptor.tileSize = parseInt (image.getAttribute ("TileSize"));
- descriptor.overlap = parseInt (image.getAttribute ("Overlap"));
- descriptor.suffix = "." + image.getAttribute ("Format")
- descriptor.posterSize = descriptor.tileSize;
-
- this.suffix = descriptor.suffix;
- this.fullZoomLevel = Math.ceil (Math.log (Math.max (descriptor.width, descriptor.height)) / Math.LN2);
-
- descriptor.minZoom = -this.fullZoomLevel;
- var posterZoomLevel = Math.ceil (Math.log (descriptor.tileSize) / Math.LN2);
- this.posterName = this.getImageFilename (0, 0, posterZoomLevel - this.fullZoomLevel);
- return descriptor;
- },
-
- setPrefix : function (prefix) {
- this.prefix = prefix;
- },
-
- getPosterFilename : function () {
- return this.posterName;
- },
-
- getFilename : function (name) {
- return this.parameters.basePath + this.prefix + "/" + name;
- },
-
- getImageFilename : function (tileX, tileY, zoomLevel) {
- var dziZoomLevel = this.fullZoomLevel + zoomLevel;
- var key = dziZoomLevel + "/" + tileX + "_" + tileY + this.suffix;
- return this.getFilename (key);
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new instance of a <code>.bigshot</code> archive filesystem adapter.
- *
- * @class Bigshot archive filesystem.
- * @param {bigshot.ImageParameters|bigshot.VRPanoramaParameters} parameters the associated image parameters
- * @augments bigshot.FileSystem
- * @constructor
- */
-bigshot.ArchiveFileSystem = function (parameters) {
- this.indexSize = 0;
- this.offset = 0;
- this.index = {};
- this.prefix = "";
- this.suffix = "";
- this.parameters = parameters;
-
- var browser = new bigshot.Browser ();
- var req = browser.createXMLHttpRequest ();
- req.open("GET", this.parameters.basePath + "&start=0&length=24&type=text/plain", false);
- req.send(null);
- if(req.status == 200) {
- if (req.responseText.substring (0, 7) != "BIGSHOT") {
- alert ("\"" + this.parameters.basePath + "\" is not a valid bigshot file");
- return;
- }
- this.indexSize = parseInt (req.responseText.substring (8), 16);
- this.offset = this.indexSize + 24;
-
- req.open("GET", this.parameters.basePath + "&type=text/plain&start=24&length=" + this.indexSize, false);
- req.send(null);
- if(req.status == 200) {
- var substrings = req.responseText.split (":");
- for (var i = 0; i < substrings.length; i += 3) {
- this.index[substrings[i]] = {
- start : parseInt (substrings[i + 1]) + this.offset,
- length : parseInt (substrings[i + 2])
- };
- }
- } else {
- alert ("The index of \"" + this.parameters.basePath + "\" could not be loaded: " + req.status);
- }
- } else {
- alert ("The header of \"" + this.parameters.basePath + "\" could not be loaded: " + req.status);
- }
-};
-
-
-bigshot.ArchiveFileSystem.prototype = {
- getDescriptor : function () {
- this.browser = new bigshot.Browser ();
- var req = this.browser.createXMLHttpRequest ();
-
- req.open("GET", this.getFilename ("descriptor"), false);
- req.send(null);
- var descriptor = {};
- if(req.status == 200) {
- var substrings = req.responseText.split (":");
- for (var i = 0; i < substrings.length; i += 2) {
- if (substrings[i] == "suffix") {
- descriptor[substrings[i]] = substrings[i + 1];
- } else {
- descriptor[substrings[i]] = parseInt (substrings[i + 1]);
- }
- }
- this.suffix = descriptor.suffix;
- return descriptor;
- } else {
- throw new Error ("Unable to find descriptor.");
- }
- },
-
- getPosterFilename : function () {
- return this.getFilename ("poster" + this.suffix);
- },
-
- getFilename : function (name) {
- name = this.getPrefix () + name;
- if (!this.index[name] && console) {
- console.log ("Can't find " + name);
- }
- var f = this.parameters.basePath + "&start=" + this.index[name].start + "&length=" + this.index[name].length;
- if (name.substring (name.length - 4) == ".jpg") {
- f = f + "&type=image/jpeg";
- } else if (name.substring (name.length - 4) == ".png") {
- f = f + "&type=image/png";
- } else {
- f = f + "&type=text/plain";
- }
- return f;
- },
-
- getImageFilename : function (tileX, tileY, zoomLevel) {
- var key = (-zoomLevel) + "/" + tileX + "_" + tileY + this.suffix;
- return this.getFilename (key);
- },
-
- getPrefix : function () {
- if (this.prefix) {
- return this.prefix + "/";
- } else {
- return "";
- }
- },
-
- setPrefix : function (prefix) {
- this.prefix = prefix;
- }
-}
-
-bigshot.Object.validate ("bigshot.ArchiveFileSystem", bigshot.FileSystem);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Abstract base class.
- */
-bigshot.VRTileCache = function () {
-}
-
-bigshot.VRTileCache.prototype = {
- /**
- * Returns the texture object for the given tile-x, tile-y and zoom level.
- * The return type is dependent on the renderer. The WebGL renderer, for example
- * uses a tile cache that returns WebGL textures, while the CSS3D renderer
- * returns HTML img or canvas elements.
- */
- getTexture : function (tileX, tileY, zoomLevel) {},
-
- /**
- * Purges the cache of old entries.
- *
- * @type void
- */
- purge : function () {},
-
- /**
- * Disposes the cache and all its entries.
- *
- * @type void
- */
- dispose : function () {}
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class A VR tile cache backed by a {@link bigshot.ImageTileCache}.
- * @augments bigshot.VRTileCache
- */
-bigshot.ImageVRTileCache = function (onloaded, onCacheInit, parameters) {
- this.imageTileCache = new bigshot.ImageTileCache (onloaded, onCacheInit, parameters);
-
- // Keep the imageTileCache from wrapping around.
- this.imageTileCache.setMaxTiles (999999, 999999);
-}
-
-bigshot.ImageVRTileCache.prototype = {
- getTexture : function (tileX, tileY, zoomLevel) {
- var res = this.imageTileCache.getImage (tileX, tileY, zoomLevel);
- return res;
- },
-
- purge : function () {
- this.imageTileCache.resetUsed ();
- },
-
- dispose : function () {
-
- }
-}
-
-bigshot.Object.validate ("bigshot.ImageVRTileCache", bigshot.VRTileCache);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new cache instance.
- *
- * @class Tile texture cache for a {@link bigshot.VRFace}.
- * @augments bigshot.VRTileCache
- * @param {function()} onLoaded function that is called whenever a texture tile has been loaded
- * @param {function()} onCacheInit function that is called when the texture cache is fully initialized
- * @param {bigshot.VRPanoramaParameters} parameters image parameters
- * @param {bigshot.WebGL} _webGl WebGL instance to use
- */
-bigshot.TextureTileCache = function (onLoaded, onCacheInit, parameters, _webGl) {
- this.parameters = parameters;
- this.webGl = _webGl;
-
- /**
- * Reduced-resolution preview of the full image.
- * Loaded from the "poster" image created by
- * MakeImagePyramid
- *
- * @private
- * @type HTMLImageElement
- */
- this.fullImage = parameters.dataLoader.loadImage (parameters.fileSystem.getPosterFilename (), onCacheInit);
-
- /**
- * Maximum number of WebGL textures in the cache. This is the
- * "L1" cache.
- *
- * @private
- * @type int
- */
- this.maxTextureCacheSize = 512;
-
- /**
- * Maximum number of HTMLImageElement images in the cache. This is the
- * "L2" cache.
- *
- * @private
- * @type int
- */
- this.maxImageCacheSize = 2048;
- this.cachedTextures = {};
- this.cachedImages = {};
- this.requestedImages = {};
- this.lastOnLoadFiredAt = 0;
- this.imageRequests = 0;
- this.partialImageSize = parameters.tileSize / 8;
- this.imageLruMap = new bigshot.LRUMap ();
- this.textureLruMap = new bigshot.LRUMap ();
- this.onLoaded = onLoaded;
- this.browser = new bigshot.Browser ();
- this.disposed = false;
-}
-
-bigshot.TextureTileCache.prototype = {
-
- getPartialTexture : function (tileX, tileY, zoomLevel) {
- if (this.fullImage.complete) {
- var canvas = document.createElement ("canvas");
- if (!canvas["width"]) {
- return null;
- }
- canvas.width = this.partialImageSize;
- canvas.height = this.partialImageSize;
- var ctx = canvas.getContext ("2d");
-
- var posterScale = this.parameters.posterSize / Math.max (this.parameters.width, this.parameters.height);
-
- var posterWidth = Math.floor (posterScale * this.parameters.width);
- var posterHeight = Math.floor (posterScale * this.parameters.height);
-
- var tileSizeAtZoom = posterScale * (this.parameters.tileSize - this.parameters.overlap) / Math.pow (2, zoomLevel);
- var sx = Math.floor (tileSizeAtZoom * tileX);
- var sy = Math.floor (tileSizeAtZoom * tileY);
- var sw = Math.floor (tileSizeAtZoom);
- var sh = Math.floor (tileSizeAtZoom);
- var dw = this.partialImageSize + 2;
- var dh = this.partialImageSize + 2;
-
- if (sx + sw > posterWidth) {
- sw = posterWidth - sx;
- dw = this.partialImageSize * (sw / Math.floor (tileSizeAtZoom));
- }
- if (sy + sh > posterHeight) {
- sh = posterHeight - sy;
- dh = this.partialImageSize * (sh / Math.floor (tileSizeAtZoom));
- }
-
- ctx.drawImage (this.fullImage, sx, sy, sw, sh, -1, -1, dw, dh);
-
- return this.webGl.createImageTextureFromImage (canvas, this.parameters.textureMinFilter, this.parameters.textureMagFilter);
- } else {
- return null;
- }
- },
-
- setCachedTexture : function (key, newTexture) {
- if (this.cachedTextures[key] != null) {
- this.webGl.deleteTexture (this.cachedTextures[key]);
- }
- this.cachedTextures[key] = newTexture;
- },
-
- getTexture : function (tileX, tileY, zoomLevel) {
- var key = this.getImageKey (tileX, tileY, zoomLevel);
- this.textureLruMap.access (key);
- this.imageLruMap.access (key);
-
- if (this.cachedTextures[key]) {
- return this.cachedTextures[key];
- } else if (this.cachedImages[key]) {
- this.setCachedTexture (key, this.webGl.createImageTextureFromImage (this.cachedImages[key], this.parameters.textureMinFilter, this.parameters.textureMagFilter));
- return this.cachedTextures[key];
- } else {
- this.requestImage (tileX, tileY, zoomLevel);
- var partial = this.getPartialTexture (tileX, tileY, zoomLevel);
- if (partial) {
- this.setCachedTexture (key, partial);
- }
- return partial;
- }
- },
-
- requestImage : function (tileX, tileY, zoomLevel) {
- var key = this.getImageKey (tileX, tileY, zoomLevel);
- if (!this.requestedImages[key]) {
- this.imageRequests++;
- var that = this;
- this.parameters.dataLoader.loadImage (this.getImageFilename (tileX, tileY, zoomLevel), function (tile) {
- if (that.disposed) {
- return;
- }
- that.cachedImages[key] = tile;
- that.setCachedTexture (key, that.webGl.createImageTextureFromImage (tile, that.parameters.textureMinFilter, that.parameters.textureMagFilter));
- delete that.requestedImages[key];
- that.imageRequests--;
- var now = new Date();
- if (that.imageRequests == 0 || now.getTime () > (that.lastOnLoadFiredAt + 50)) {
- that.lastOnLoadFiredAt = now.getTime ();
- that.onLoaded ();
- }
- });
- this.requestedImages[key] = true;
- }
- },
-
- purge : function () {
- var that = this;
- this.purgeCache (this.textureLruMap, this.cachedTextures, this.maxTextureCacheSize, function (leastUsedKey) {
- that.webGl.deleteTexture (that.cachedTextures[leastUsedKey]);
- });
- this.purgeCache (this.imageLruMap, this.cachedImages, this.maxImageCacheSize, function (leastUsedKey) {
- });
- },
-
- purgeCache : function (lruMap, cache, maxCacheSize, onEvict) {
- for (var i = 0; i < 64; ++i) {
- if (lruMap.getSize () > maxCacheSize) {
- var leastUsed = lruMap.leastUsed ();
- lruMap.remove (leastUsed);
- if (onEvict) {
- onEvict (leastUsed);
- }
- delete cache[leastUsed];
- } else {
- break;
- }
- }
- },
-
- getImageKey : function (tileX, tileY, zoomLevel) {
- return "I" + tileX + "_" + tileY + "_" + zoomLevel;
- },
-
- getImageFilename : function (tileX, tileY, zoomLevel) {
- var f = this.parameters.fileSystem.getImageFilename (tileX, tileY, zoomLevel);
- return f;
- },
-
- dispose : function () {
- this.disposed = true;
- for (var k in this.cachedTextures) {
- this.webGl.deleteTexture (this.cachedTextures[k]);
- }
- }
-};
-
-
-bigshot.Object.validate ("bigshot.TextureTileCache", bigshot.VRTileCache);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new VR cube face.
- *
- * @class a VR cube face. The {@link bigshot.VRPanorama} instance holds
- * six of these.
- *
- * @param {bigshot.VRPanorama} owner the VR panorama this face is part of.
- * @param {String} key the identifier for the face. "f" is front, "b" is back, "u" is
- * up, "d" is down, "l" is left and "r" is right.
- * @param {bigshot.Point3D} topLeft_ the top-left corner of the quad.
- * @param {number} width_ the length of the sides of the face, expressed in multiples of u and v.
- * @param {bigshot.Point3D} u basis vector going from the top left corner along the top edge of the face
- * @param {bigshot.Point3D} v basis vector going from the top left corner along the left edge of the face
- */
-bigshot.VRFace = function (owner, key, topLeft_, width_, u, v, onLoaded) {
- var that = this;
- this.owner = owner;
- this.key = key;
- this.topLeft = topLeft_;
- this.width = width_;
- this.u = u;
- this.v = v;
- this.updated = false;
- this.parameters = new Object ();
-
- for (var k in this.owner.getParameters ()) {
- this.parameters[k] = this.owner.getParameters ()[k];
- }
-
- bigshot.setupFileSystem (this.parameters);
- this.parameters.fileSystem.setPrefix ("face_" + key);
- this.parameters.merge (this.parameters.fileSystem.getDescriptor (), false);
-
-
- /**
- * Texture cache.
- *
- * @private
- */
- this.tileCache = owner.renderer.createTileCache (function () {
- that.updated = true;
- owner.renderUpdated (bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE);
- }, onLoaded, this.parameters);
-
- this.fullSize = this.parameters.width;
- this.overlap = this.parameters.overlap;
- this.tileSize = this.parameters.tileSize;
-
- this.minDivisions = 0;
- var fullZoom = Math.log (this.fullSize - this.overlap) / Math.LN2;
- var singleTile = Math.log (this.tileSize - this.overlap) / Math.LN2;
- this.maxDivisions = Math.floor (fullZoom - singleTile);
- this.maxTesselation = this.parameters.maxTesselation >= 0 ? this.parameters.maxTesselation : this.maxDivisions;
-}
-
-bigshot.VRFace.prototype = {
- browser : new bigshot.Browser (),
-
- dispose : function () {
- this.tileCache.dispose ();
- },
-
- /**
- * Utility function to do a multiply-and-add of a 3d point.
- *
- * @private
- * @param p {bigshot.Point3D} the point to multiply
- * @param m {number} the number to multiply the elements of p with
- * @param a {bigshot.Point3D} the point to add
- * @return p * m + a
- */
- pt3dMultAdd : function (p, m, a) {
- return {
- x : p.x * m + a.x,
- y : p.y * m + a.y,
- z : p.z * m + a.z
- };
- },
-
- /**
- * Utility function to do an element-wise multiply of a 3d point.
- *
- * @private
- * @param p {bigshot.Point3D} the point to multiply
- * @param m {number} the number to multiply the elements of p with
- * @return p * m
- */
- pt3dMult : function (p, m) {
- return {
- x : p.x * m,
- y : p.y * m,
- z : p.z * m
- };
- },
-
- /**
- * Creates a textured quad.
- *
- * @private
- */
- generateFace : function (scene, topLeft, width, tx, ty, divisions) {
- width *= this.tileSize / (this.tileSize - this.overlap);
- var texture = this.tileCache.getTexture (tx, ty, -this.maxDivisions + divisions);
- scene.addQuad (this.owner.renderer.createTexturedQuad (
- topLeft,
- this.pt3dMult (this.u, width),
- this.pt3dMult (this.v, width),
- texture
- )
- );
- },
-
- VISIBLE_NONE : 0,
- VISIBLE_SOME : 1,
- VISIBLE_ALL : 2,
-
- /**
- * Tests whether the point is in the axis-aligned rectangle.
- *
- * @private
- * @param point the point
- * @param min top left corner of the rectangle
- * @param max bottom right corner of the rectangle
- */
- pointInRect : function (point, min, max) {
- return (point.x >= min.x && point.y >= min.y && point.x < max.x && point.y < max.y);
- },
-
- /**
- * Intersects a quadrilateral with the view frustum.
- * The test is a simple rectangle intersection of the AABB of
- * the transformed quad with the viewport.
- *
- * @private
- * @return VISIBLE_NONE, VISIBLE_SOME or VISIBLE_ALL
- */
- intersectWithView : function intersectWithView (transformed) {
- var numNull = 0;
- var tf = [];
- var tfl = transformed.length;
- for (var i = 0; i < tfl; ++i) {
- if (transformed[i] == null) {
- numNull++;
- } else {
- tf.push (transformed[i]);
- }
- }
- if (numNull == 4) {
- return this.VISIBLE_NONE;
- }
-
- var minX = tf[0].x;
- var minY = tf[0].y;
-
- var maxX = minX;
- var maxY = minY;
-
- var viewMinX = 0;
- var viewMinY = 0;
-
- var viewMaxX = this.viewportWidth;
- var viewMaxY = this.viewportHeight;
-
- var pointsInViewport = 0;
- var tl = tf.length;
- for (var i = 1; i < tl; ++i) {
- var tix = tf[i].x;
- var tiy = tf[i].y;
-
- minX = minX < tix ? minX : tix;
- minY = minY < tiy ? minY : tiy;
-
-
- maxX = maxX > tix ? maxX : tix;
- maxY = maxY > tiy ? maxY : tiy;
- }
-
- var iminX = minX > viewMinX ? minX : viewMinX;
- var iminY = minY > viewMinY ? minY : viewMinY;
-
- var imaxX = maxX < viewMaxX ? maxX : viewMaxX;
- var imaxY = maxY < viewMaxY ? maxY : viewMaxY;
-
- if (iminX <= imaxX && iminY <= imaxY) {
- return this.VISIBLE_SOME;
- }
-
- return this.VISIBLE_NONE;
- },
-
- /**
- * Quick and dirty computation of the on-screen distance in pixels
- * between two 2d points. We use the max of the x and y differences.
- * In case a point is null (that is, it's not on the screen), we
- * return an arbitrarily high number.
- *
- * @private
- */
- screenDistance : function screenDistance (p0, p1) {
- if (p0 == null || p1 == null) {
- return 0;
- }
- return Math.max (Math.abs (p0.x - p1.x), Math.abs (p0.y - p1.y));
- },
-
- transformToScreen : function transformToScreen (v) {
- return this.owner.renderer.transformToScreen (v);
- },
-
- /**
- * Optionally subdivides a quad into fourn new quads, depending on the
- * position and on-screen size of the quad.
- *
- * @private
- * @param {bigshot.WebGLTexturedQuadScene} scene the scene to add quads to
- * @param {bigshot.Point3D} topLeft the top left corner of this quad
- * @param {number} width the sides of the quad, expressed in multiples of u and v
- * @param {int} divisions the current number of divisions done (increases by one for each
- * split-in-four).
- * @param {int} tx the tile column this face is in
- * @param {int} ty the tile row this face is in
- */
- generateSubdivisionFace : function generateSubdivisionFace (scene, topLeft, width, divisions, tx, ty, transformed) {
- if (!transformed) {
- transformed = new Array (4);
- transformed[0] = this.transformToScreen (topLeft);
- var topRight = this.pt3dMultAdd (this.u, width, topLeft);
- transformed[1] = this.transformToScreen (topRight);
-
- var bottomLeft = this.pt3dMultAdd (this.v, width, topLeft);
- transformed[3] = this.transformToScreen (bottomLeft);
-
- var bottomRight = this.pt3dMultAdd (this.v, width, topRight);
- transformed[2] = this.transformToScreen (bottomRight);
- };
-
- var numVisible = this.intersectWithView (transformed);
-
- if (numVisible == this.VISIBLE_NONE) {
- return;
- }
-
- var dmax = 0;
- for (var i = 0; i < transformed.length; ++i) {
- var next = (i + 1) % 4;
- dmax = Math.max (this.screenDistance (transformed[i], transformed[next]), dmax);
- }
-
- // Convert the distance to physical pixels
- dmax *= this.owner.browser.getDevicePixelScale ();
-
- if (divisions < this.minDivisions
- ||
- (
- (
- dmax > this.owner.maxTextureMagnification * (this.tileSize - this.overlap)
- ) && divisions < this.maxDivisions && divisions < this.maxTesselation
- )
- ) {
- var center = this.pt3dMultAdd ({x: this.u.x + this.v.x, y: this.u.y + this.v.y, z: this.u.z + this.v.z }, width / 2, topLeft);
- var midTop = this.pt3dMultAdd (this.u, width / 2, topLeft);
- var midLeft = this.pt3dMultAdd (this.v, width / 2, topLeft);
-
- var tCenter = this.transformToScreen (center);
- var tMidLeft = this.transformToScreen (midLeft);
- var tMidTop = this.transformToScreen (midTop);
- var tMidRight = this.transformToScreen (this.pt3dMultAdd (this.u, width, midLeft));
- var tMidBottom = this.transformToScreen (this.pt3dMultAdd (this.v, width, midTop));
-
- this.generateSubdivisionFace (scene, topLeft, width / 2, divisions + 1, tx * 2, ty * 2, [transformed[0], tMidTop, tCenter, tMidLeft]);
- this.generateSubdivisionFace (scene, midTop, width / 2, divisions + 1, tx * 2 + 1, ty * 2, [tMidTop, transformed[1], tMidRight, tCenter]);
- this.generateSubdivisionFace (scene, midLeft, width / 2, divisions + 1, tx * 2, ty * 2 + 1, [tMidLeft, tCenter, tMidBottom, transformed[3]]);
- this.generateSubdivisionFace (scene, center, width / 2, divisions + 1, tx * 2 + 1, ty * 2 + 1, [tCenter, tMidRight, transformed[2], tMidBottom]);
- } else {
- this.generateFace (scene, topLeft, width, tx, ty, divisions);
- }
- },
-
- /**
- * Tests if the face has had any updated texture
- * notifications from the tile cache.
- *
- * @public
- */
- isUpdated : function () {
- return this.updated;
- },
-
- /**
- * Renders this face into a scene.
- *
- * @public
- * @param {bigshot.WebGLTexturedQuadScene} scene the scene to render into
- */
- render : function (scene) {
- this.updated = false;
- this.viewportWidth = this.owner.renderer.getViewportWidth ();
- this.viewportHeight = this.owner.renderer.getViewportHeight ();
- this.generateSubdivisionFace (scene, this.topLeft, this.width, 0, 0, 0);
- },
-
- /**
- * Performs post-render cleanup.
- */
- endRender : function () {
- this.tileCache.purge ();
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class WebGL utility functions.
- */
-bigshot.WebGLUtil = {
- /**
- * Flag indicating whether we want to wrap the WebGL context in a
- * WebGLDebugUtils.makeDebugContext. Defaults to false.
- *
- * @type boolean
- * @public
- */
- debug : false,
-
- /**
- * List of context identifiers WebGL may be accessed via.
- *
- * @type String[]
- * @private
- */
- contextNames : ["webgl", "experimental-webgl"],
-
- /**
- * Utility function for creating a context given a canvas and
- * a context identifier.
- * @type WebGLRenderingContext
- * @private
- */
- createContext0 : function (canvas, context) {
- var gl = this.debug
- ?
- WebGLDebugUtils.makeDebugContext(canvas.getContext(context))
- :
- canvas.getContext (context);
- return gl;
- },
-
- /**
- * Creates a WebGL context for the given canvas, if possible.
- *
- * @public
- * @type WebGLRenderingContext
- * @param {HTMLCanvasElement} canvas the canvas
- * @return The WebGL context
- * @throws {Error} If WebGL isn't supported.
- */
- createContext : function (canvas) {
- for (var i = 0; i < this.contextNames.length; ++i) {
- try {
- var gl = this.createContext0 (canvas, this.contextNames[i]);
- if (gl) {
- return gl;
- }
- } catch (e) {
- }
- }
- throw new Error ("Could not initialize WebGL.");
- },
-
- /**
- * Tests whether WebGL is supported.
- *
- * @type boolean
- * @public
- * @return true If WebGL is supported, false otherwise.
- */
- isWebGLSupported : function () {
- var canvas = document.createElement ("canvas");
- if (!canvas["width"]) {
- // Not even canvas support
- return false;
- }
-
- try {
- this.createContext (canvas);
- return true;
- } catch (e) {
- // No WebGL support
- return false;
- }
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new transformation stack, initialized to the identity transform.
- *
- * @class A 3D transformation stack.
- */
-bigshot.TransformStack = function () {
- /**
- * The current transform matrix.
- *
- * @type Matrix
- */
- this.mvMatrix = null;
-
- /**
- * The object-to-world transform matrix stack.
- *
- * @type Matrix[]
- */
- this.mvMatrixStack = [];
-
- this.reset ();
-}
-
-bigshot.TransformStack.prototype = {
- /**
- * Pushes the current world transform onto the stack
- * and returns a new, identical one.
- *
- * @return the new world transform matrix
- * @param {Matrix} [matrix] the new world transform.
- * If omitted, the current is used
- * @type Matrix
- */
- push : function (matrix) {
- if (matrix) {
- this.mvMatrixStack.push (matrix.dup());
- this.mvMatrix = matrix.dup();
- return mvMatrix;
- } else {
- this.mvMatrixStack.push (this.mvMatrix.dup());
- return mvMatrix;
- }
- },
-
- /**
- * Pops the last-pushed world transform off the stack, thereby restoring it.
- *
- * @type Matrix
- * @return the previously-pushed matrix
- */
- pop : function () {
- if (this.mvMatrixStack.length == 0) {
- throw new Error ("Invalid popMatrix!");
- }
- this.mvMatrix = this.mvMatrixStack.pop();
- return mvMatrix;
- },
-
- /**
- * Resets the world transform to the identity transform.
- */
- reset : function () {
- this.mvMatrix = Matrix.I(4);
- },
-
- /**
- * Multiplies the current world transform with a matrix.
- *
- * @param {Matrix} matrix the matrix to multiply with
- */
- multiply : function (matrix) {
- this.mvMatrix = matrix.x (this.mvMatrix);
- },
-
- /**
- * Adds a translation to the world transform matrix.
- *
- * @param {bigshot.Point3D} vector the translation vector
- */
- translate : function (vector) {
- var m = Matrix.Translation($V([vector.x, vector.y, vector.z])).ensure4x4 ();
- this.multiply (m);
- },
-
- /**
- * Adds a rotation to the world transform matrix.
- *
- * @param {number} ang the angle in degrees to rotate
- * @param {bigshot.Point3D} vector the rotation vector
- */
- rotate : function (ang, vector) {
- var arad = ang * Math.PI / 180.0;
- var m = Matrix.Rotation(arad, $V([vector.x, vector.y, vector.z])).ensure4x4 ();
- this.multiply (m);
- },
-
- /**
- * Adds a rotation around the x-axis to the world transform matrix.
- *
- * @param {number} ang the angle in degrees to rotate
- */
- rotateX : function (ang) {
- this.rotate (ang, { x : 1, y : 0, z : 0 });
- },
-
- /**
- * Adds a rotation around the y-axis to the world transform matrix.
- *
- * @param {number} ang the angle in degrees to rotate
- */
- rotateY : function (ang) {
- this.rotate (ang, { x : 0, y : 1, z : 0 });
- },
-
- /**
- * Adds a rotation around the z-axis to the world transform matrix.
- *
- * @param {number} ang the angle in degrees to rotate
- */
- rotateZ : function (ang) {
- this.rotate (ang, { x : 0, y : 0, z : 1 });
- },
-
- /**
- * Multiplies the current matrix with a
- * perspective transformation matrix.
- *
- * @param {number} fovy vertical field of view
- * @param {number} aspect viewport aspect ratio
- * @param {number} znear near image plane
- * @param {number} zfar far image plane
- */
- perspective : function (fovy, aspect, znear, zfar) {
- var m = makePerspective (fovy, aspect, znear, zfar);
- this.multiply (m);
- },
-
- matrix : function () {
- return this.mvMatrix;
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new WebGL wrapper instance.
- *
- * @class WebGL wrapper for common {@link bigshot.VRPanorama} uses.
- * @param {HTMLCanvasElement} canvas_ the canvas
- * @see #onresize()
- */
-bigshot.WebGL = function (canvas_) {
- /**
- * The html canvas element we'll be rendering in.
- *
- * @type HTMLCanvasElement
- */
- this.canvas = canvas_;
-
- /**
- * Our WebGL context.
- *
- * @type WebGLRenderingContext
- */
- this.gl = bigshot.WebGLUtil.createContext (this.canvas);
-
- /**
- * The current object-to-world transform matrix.
- *
- * @type bigshot.TransformStack
- */
- this.mvMatrix = new bigshot.TransformStack ();
-
- /**
- * The current perspective transform matrix.
- *
- * @type bigshot.TransformStack
- */
- this.pMatrix = new bigshot.TransformStack ();
-
- /**
- * The current shader program.
- */
- this.shaderProgram = null;
-
- this.onresize ();
-}
-
-bigshot.WebGL.prototype = {
- /**
- * Must be called when the canvas element is resized.
- *
- * @public
- */
- onresize : function () {
- this.gl.viewportWidth = this.canvas.width;
- this.gl.viewportHeight = this.canvas.height;
- },
-
- /**
- * Fragment shader. Taken from the "Learning WebGL" lessons:
- * http://learningwebgl.com/blog/?p=571
- */
- fragmentShader :
- "#ifdef GL_ES\n" +
- " precision highp float;\n" +
- "#endif\n" +
- "\n" +
- "varying vec2 vTextureCoord;\n" +
- "\n" +
- "uniform sampler2D uSampler;\n" +
- "\n" +
- "void main(void) {\n" +
- " gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));\n" +
- "}\n",
-
- /**
- * Vertex shader. Taken from the "Learning WebGL" lessons:
- * http://learningwebgl.com/blog/?p=571
- */
- vertexShader :
- "attribute vec3 aVertexPosition;\n" +
- "attribute vec2 aTextureCoord;\n" +
- "\n" +
- "uniform mat4 uMVMatrix;\n" +
- "uniform mat4 uPMatrix;\n" +
- "\n" +
- "varying vec2 vTextureCoord;\n" +
- "\n" +
- "void main(void) {\n" +
- " gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\n" +
- " vTextureCoord = aTextureCoord;\n" +
- "}",
-
- /**
- * Creates a new shader.
- *
- * @type WebGLShader
- * @param {String} source the source code
- * @param {int} type the shader type, one of WebGLRenderingContext.FRAGMENT_SHADER or
- * WebGLRenderingContext.VERTEX_SHADER
- */
- createShader : function (source, type) {
- var shader = this.gl.createShader (type);
- this.gl.shaderSource (shader, source);
- this.gl.compileShader (shader);
-
- if (!this.gl.getShaderParameter (shader, this.gl.COMPILE_STATUS)) {
- alert (this.gl.getShaderInfoLog (shader));
- return null;
- }
-
- return shader;
- },
-
- /**
- * Creates a new fragment shader.
- *
- * @type WebGLShader
- * @param {String} source the source code
- */
- createFragmentShader : function (source) {
- return this.createShader (source, this.gl.FRAGMENT_SHADER);
- },
-
- /**
- * Creates a new vertex shader.
- *
- * @type WebGLShader
- * @param {String} source the source code
- */
- createVertexShader : function (source) {
- return this.createShader (source, this.gl.VERTEX_SHADER);
- },
-
- /**
- * Initializes the shaders.
- */
- initShaders : function () {
- this.shaderProgram = this.gl.createProgram ();
- this.gl.attachShader (this.shaderProgram, this.createVertexShader (this.vertexShader));
- this.gl.attachShader (this.shaderProgram, this.createFragmentShader (this.fragmentShader));
- this.gl.linkProgram (this.shaderProgram);
-
- if (!this.gl.getProgramParameter (this.shaderProgram, this.gl.LINK_STATUS)) {
- throw new Error ("Could not initialise shaders");
- return;
- }
-
- this.gl.useProgram (this.shaderProgram);
-
- this.shaderProgram.vertexPositionAttribute = this.gl.getAttribLocation (this.shaderProgram, "aVertexPosition");
- this.gl.enableVertexAttribArray (this.shaderProgram.vertexPositionAttribute);
-
- this.shaderProgram.textureCoordAttribute = this.gl.getAttribLocation (this.shaderProgram, "aTextureCoord");
- this.gl.enableVertexAttribArray (this.shaderProgram.textureCoordAttribute);
-
- this.shaderProgram.pMatrixUniform = this.gl.getUniformLocation(this.shaderProgram, "uPMatrix");
- this.shaderProgram.mvMatrixUniform = this.gl.getUniformLocation(this.shaderProgram, "uMVMatrix");
- this.shaderProgram.samplerUniform = this.gl.getUniformLocation(this.shaderProgram, "uSampler");
- },
-
-
- /**
- * Sets the matrix parameters ("uniforms", since the variables are declared as uniform) in the shaders.
- */
- setMatrixUniforms : function () {
- this.gl.uniformMatrix4fv (this.shaderProgram.pMatrixUniform, false, new Float32Array(this.pMatrix.matrix().flatten()));
- this.gl.uniformMatrix4fv (this.shaderProgram.mvMatrixUniform, false, new Float32Array(this.mvMatrix.matrix().flatten()));
- },
-
- /**
- * Creates a texture from an image.
- *
- * @param {HTMLImageElement or HTMLCanvasElement} image the image
- * @type WebGLTexture
- * @return An initialized texture
- */
- createImageTextureFromImage : function (image, minFilter, magFilter) {
- var texture = this.gl.createTexture();
- this.handleImageTextureLoaded (this, texture, image, minFilter, magFilter);
- return texture;
- },
-
- /**
- * Creates a texture from a source url.
- *
- * @param {String} source the URL of the image
- * @return WebGLTexture
- */
- createImageTextureFromSource : function (source, minFilter, magFilter) {
- var image = new Image();
- var texture = this.gl.createTexture();
-
- var that = this;
- image.onload = function () {
- that.handleImageTextureLoaded (that, texture, image, minFilter, magFilter);
- }
-
- image.src = source;
-
- return texture;
- },
-
- /**
- * Uploads the image data to the texture memory. Called when the texture image
- * has finished loading.
- *
- * @private
- */
- handleImageTextureLoaded : function (that, texture, image, minFilter, magFilter) {
- that.gl.bindTexture (that.gl.TEXTURE_2D, texture);
- that.gl.texImage2D (that.gl.TEXTURE_2D, 0, that.gl.RGBA, that.gl.RGBA, that.gl.UNSIGNED_BYTE, image);
- that.gl.texParameteri (that.gl.TEXTURE_2D, that.gl.TEXTURE_MAG_FILTER, magFilter ? magFilter : that.gl.NEAREST);
- that.gl.texParameteri (that.gl.TEXTURE_2D, that.gl.TEXTURE_MIN_FILTER, minFilter ? minFilter : that.gl.NEAREST);
- that.gl.texParameteri (that.gl.TEXTURE_2D, that.gl.TEXTURE_WRAP_S, that.gl.CLAMP_TO_EDGE);
- that.gl.texParameteri (that.gl.TEXTURE_2D, that.gl.TEXTURE_WRAP_T, that.gl.CLAMP_TO_EDGE);
- if (minFilter == that.gl.NEAREST_MIPMAP_NEAREST
- || minFilter == that.gl.LINEAR_MIPMAP_NEAREST
- || minFilter == that.gl.NEAREST_MIPMAP_LINEAR
- || minFilter == that.gl.LINEAR_MIPMAP_LINEAR) {
- that.gl.generateMipmap(that.gl.TEXTURE_2D);
- }
-
- that.gl.bindTexture (that.gl.TEXTURE_2D, null);
- },
-
- deleteTexture : function (texture) {
- this.gl.deleteTexture (texture);
- },
-
- dispose : function () {
- delete this.canvas;
- delete this.gl;
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Abstract base for 3d rendering system.
- */
-bigshot.VRRenderer = function () {
-}
-
-bigshot.VRRenderer.prototype = {
- /**
- * Creates a new {@link bigshot.VRTileCache}, appropriate for the rendering system.
- *
- * @param {function()} onloaded function that is called whenever a texture tile has been loaded
- * @param {function()} onCacheInit function that is called when the texture cache is fully initialized
- * @param {bigshot.VRPanoramaParameters} parameters the parameters for the panorama
- */
- createTileCache : function (onloaded, onCacheInit, parameters) {},
-
- /**
- * Creates a bigshot.TexturedQuadScene.
- */
- createTexturedQuadScene : function () {},
-
- /**
- * Creates a bigshot.TexturedQuad.
- *
- * @param {bigshot.Point3D} p the top-left corner of the quad
- * @param {bigshot.Point3D} u a vector going along the top edge of the quad
- * @param {bigshot.Point3D} v a vector going down the left edge of the quad
- * @param {Object} texture a texture to use for the quad. The texture type may vary among different
- * VRRenderer implementations. The VRTileCache that is created using the createTileCache method will
- * supply the correct type.
- */
- createTexturedQuad : function (p, u, v, texture) {},
-
- /**
- * Returns the viewport width, in pixels.
- *
- * @type int
- */
- getViewportWidth : function () {},
-
- /**
- * Returns the viewport height, in pixels.
- *
- * @type int
- */
- getViewportHeight : function () {},
-
- /**
- * Transforms a vector to world coordinates.
- *
- * @param {bigshot.Point3D} v the view-space point to transform
- */
- transformToWorld : function (v) {},
-
- /**
- * Transforms a world vector to screen coordinates.
- *
- * @param {bigshot.Point3D} worldVector the world-space point to transform
- */
- transformWorldToScreen : function (worldVector) {},
-
- /**
- * Transforms a 3D vector to screen coordinates.
- *
- * @param {bigshot.Point3D} vector the vector to transform.
- * If it is already in homogenous coordinates (4-element array)
- * the transformation is faster. Otherwise it will be converted.
- */
- transformToScreen : function (vector) {},
-
- /**
- * Disposes the renderer and associated resources.
- */
- dispose : function () {},
-
- /**
- * Called to begin a render.
- *
- * @param {bigshot.Rotation} rotation the rotation of the viewer
- * @param {number} fov the vertical field of view, in degrees
- * @param {bigshot.Point3D} translation the position of the viewer in world space
- * @param {bigshot.Rotation} rotationOffsets the rotation to apply to the VR cube
- * before the viewer rotation is applied
- */
- beginRender : function (rotation, fov, translation, rotationOffsets) {},
-
- /**
- * Called to end a render.
- */
- endRender : function () {},
-
- /**
- * Called by client code to notify the renderer that the viewport has been resized.
- */
- onresize : function () {},
-
- /**
- * Resizes the viewport.
- *
- * @param {int} w the new width of the viewport, in pixels
- * @param {int} h the new height of the viewport, in pixels
- */
- resize : function (w, h) {},
-
- /**
- * Gets the container element for the renderer. This is used
- * when calling the requestAnimationFrame API.
- */
- getElement : function () {}
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Abstract VR renderer base class.
- */
-bigshot.AbstractVRRenderer = function () {
-}
-
-bigshot.AbstractVRRenderer.prototype = {
- /**
- * Transforms a vector to world coordinates.
- *
- * @param {bigshot.Point3D} vector the vector to transform
- */
- transformToWorld : function transformToWorld (vector) {
- var world = this.mvMatrix.matrix ().xPoint3Dhom1 (vector);
-
- return world;
- },
-
- /**
- * Transforms a world vector to screen coordinates.
- *
- * @param {bigshot.Point3D} world the world-vector to transform
- */
- transformWorldToScreen : function transformWorldToScreen (world) {
- if (world.z > 0) {
- return null;
- }
-
- var screen = this.pMatrix.matrix ().xPoint3Dhom (world);
- if (Math.abs (screen.w) < Sylvester.precision) {
- return null;
- }
-
- var sx = screen.x;
- var sy = screen.y;
- var sz = screen.z;
- var vw = this.getViewportWidth ();
- var vh = this.getViewportHeight ();
-
- var r = {
- x: (vw / 2) * sx / sz + vw / 2,
- y: - (vh / 2) * sy / sz + vh / 2
- };
- return r;
- },
-
- /**
- * Transforms a vector to screen coordinates.
- *
- * @param {bigshot.Point3D} vector the vector to transform
- * @return the transformed vector, or null if the vector is nearer than the near-z plane.
- */
- transformToScreen : function transformToScreen (vector) {
- var sel = this.mvpMatrix.xPoint3Dhom (vector);
-
- if (sel.z < 0) {
- return null;
- }
-
- var sz = sel.w;
-
- if (Math.abs (sel.w) < Sylvester.precision) {
- return null;
- }
-
- var sx = sel.x;
- var sy = sel.y;
- var vw = this.getViewportWidth ();
- var vh = this.getViewportHeight ();
-
- var r = {
- x: (vw / 2) * sx / sz + vw / 2,
- y: - (vh / 2) * sy / sz + vh / 2
- };
-
- return r;
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class CSS 3D Transform-based renderer.
- * @param {HTMLElement} _container the HTML container element for the render viewport
- *
- * @augments bigshot.VRRenderer
- */
-bigshot.CSS3DVRRenderer = function (_container) {
- this.container = _container;
- this.canvasOrigin = document.createElement ("div");
-
- this.canvasOrigin.style.WebkitTransformOrigin = "0px 0px 0px";
- this.canvasOrigin.style.WebkitTransformStyle = "preserve-3d";
- this.canvasOrigin.style.WebkitPerspective= "600px";
-
- this.canvasOrigin.style.position = "relative";
- this.canvasOrigin.style.left = "50%";
- this.canvasOrigin.style.top = "50%";
-
- this.container.appendChild (this.canvasOrigin);
-
- this.viewport = document.createElement ("div");
- this.viewport.style.WebkitTransformOrigin = "0px 0px 0px";
- this.viewport.style.WebkitTransformStyle = "preserve-3d";
- this.canvasOrigin.appendChild (this.viewport);
-
- this.world = document.createElement ("div");
- this.world.style.WebkitTransformOrigin = "0px 0px 0px";
- this.world.style.WebkitTransformStyle = "preserve-3d";
- this.viewport.appendChild (this.world);
-
- this.browser.removeAllChildren (this.world);
-
- this.view = null;
-
- this.mvMatrix = new bigshot.TransformStack ();
-
- this.yaw = 0;
- this.pitch = 0;
- this.fov = 0;
- this.pMatrix = new bigshot.TransformStack ();
-
- this.onresize = function () {
- };
-
- this.viewportSize = null;
-};
-
-bigshot.CSS3DVRRenderer.prototype = {
- browser : new bigshot.Browser (),
-
- dispose : function () {
-
- },
-
- createTileCache : function (onloaded, onCacheInit, parameters) {
- return new bigshot.ImageVRTileCache (onloaded, onCacheInit, parameters);
- },
-
- createTexturedQuadScene : function () {
- return new bigshot.CSS3DTexturedQuadScene (this.world, 128, this.view);
- },
-
- createTexturedQuad : function (p, u, v, texture) {
- return new bigshot.CSS3DTexturedQuad (p, u, v, texture);
- },
-
- getElement : function () {
- return this.container;
- },
-
- supportsUpdate : function () {
- return false;
- },
-
- getViewportWidth : function () {
- if (this.viewportSize) {
- return this.viewportSize.w;
- }
- return this.browser.getElementSize (this.container).w;
- },
-
- getViewportHeight : function () {
- if (this.viewportSize) {
- return this.viewportSize.h;
- }
- return this.browser.getElementSize (this.container).h;
- },
-
- onresize : function () {
- },
-
- resize : function (w, h) {
- if (this.container.style.width != "") {
- this.container.style.width = w + "px";
- }
- if (this.container.style.height != "") {
- this.container.style.height = h + "px";
- }
- },
-
- beginRender : function (rotation, fov, translation, rotationOffsets) {
- this.viewportSize = this.browser.getElementSize (this.container);
-
- this.yaw = rotation.y;
- this.pitch = rotation.p;
- this.fov = fov;
-
- var halfFovInRad = 0.5 * fov * Math.PI / 180;
- var halfHeight = this.getViewportHeight () / 2;
- var perspectiveDistance = halfHeight / Math.tan (halfFovInRad);
-
- this.mvMatrix.reset ();
-
- this.view = translation;
- this.mvMatrix.translate (this.view);
-
-
- this.mvMatrix.rotateZ (rotationOffsets.r);
- this.mvMatrix.rotateX (rotationOffsets.p);
- this.mvMatrix.rotateY (rotationOffsets.y);
-
- this.mvMatrix.rotateY (this.yaw);
- this.mvMatrix.rotateX (this.pitch);
-
-
- this.pMatrix.reset ();
- this.pMatrix.perspective (this.fov, this.getViewportWidth () / this.getViewportHeight (), 0.1, 100.0);
-
- this.mvpMatrix = this.pMatrix.matrix ().multiply (this.mvMatrix.matrix ());
-
- this.canvasOrigin.style.WebkitPerspective= perspectiveDistance + "px";
-
- for (var i = this.world.children.length - 1; i >= 0; --i) {
- this.world.children[i].inWorld = 1;
- }
-
- this.world.style.WebkitTransform =
- "rotate3d(1,0,0," + (-rotation.p) + "deg) " +
- "rotate3d(0,1,0," + rotation.y + "deg) " +
- "rotate3d(0,1,0," + (rotationOffsets.y) + "deg) " +
- "rotate3d(1,0,0," + (-rotationOffsets.p) + "deg) " +
- "rotate3d(0,0,1," + (-rotationOffsets.r) + "deg) ";
- this.world.style.WebkitTransformStyle = "preserve-3d";
- this.world.style.WebKitBackfaceVisibility = "hidden";
-
- this.viewport.style.WebkitTransform =
- "translateZ(" + perspectiveDistance + "px)";
- },
-
- endRender : function () {
- for (var i = this.world.children.length - 1; i >= 0; --i) {
- var child = this.world.children[i];
- if (!child.inWorld || child.inWorld != 2) {
- delete child.inWorld;
- this.world.removeChild (child);
- }
- }
-
- this.viewportSize = null;
- }
-};
-
-bigshot.Object.extend (bigshot.CSS3DVRRenderer, bigshot.AbstractVRRenderer);
-bigshot.Object.validate ("bigshot.CSS3DVRRenderer", bigshot.VRRenderer);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a textured quad object.
- *
- * @class An abstraction for textured quads. Used in the
- * {@link bigshot.CSS3DTexturedQuadScene}.
- *
- * @param {bigshot.Point3D} p the top-left corner of the quad
- * @param {bigshot.Point3D} u vector pointing from p along the top edge of the quad
- * @param {bigshot.Point3D} v vector pointing from p along the left edge of the quad
- * @param {HTMLImageElement} the image to use.
- */
-bigshot.CSS3DTexturedQuad = function (p, u, v, image) {
- this.p = p;
- this.u = u;
- this.v = v;
- this.image = image;
-}
-
-bigshot.CSS3DTexturedQuad.prototype = {
- /**
- * Computes the cross product of two vectors.
- *
- * @param {bigshot.Point3D} a the first vector
- * @param {bigshot.Point3D} b the second vector
- * @type bigshot.Point3D
- * @return the cross product
- */
- crossProduct : function crossProduct (a, b) {
- return {
- x : a.y*b.z-a.z*b.y,
- y : a.z*b.x-a.x*b.z,
- z : a.x*b.y-a.y*b.x
- };
- },
-
- /**
- * Stringifies a vector as the x, y, and z components
- * separated by commas.
- *
- * @param {bigshot.Point3D} u the vector
- * @type String
- * @return the stringified vector
- */
- vecToStr : function vecToStr (u) {
- return (u.x) + "," + (u.y) + "," + (u.z);
- },
-
- /**
- * Creates a CSS3D matrix3d transform from
- * an origin point and two basis vectors
- *
- * @param {bigshot.Point3D} tl the top left corner
- * @param {bigshot.Point3D} u the vector pointing along the top edge
- * @param {bigshot.Point3D} y the vector pointing down the left edge
- * @type String
- * @return the matrix3d statement
- */
- quadTransform : function quadTransform (tl, u, v) {
- var w = this.crossProduct (u, v);
- var res =
- "matrix3d(" +
- this.vecToStr (u) + ",0," +
- this.vecToStr (v) + ",0," +
- this.vecToStr (w) + ",0," +
- this.vecToStr (tl) + ",1)";
- return res;
- },
-
- /**
- * Computes the norm of a vector.
- *
- * @param {bigshot.Point3D} vec the vector
- */
- norm : function norm (vec) {
- return Math.sqrt (vec.x * vec.x + vec.y * vec.y + vec.z * vec.z);
- },
-
- /**
- * Renders the quad.
- *
- * @param {HTMLElement} world the world element
- * @param {number} scale the scale factor to apply to world space to get CSS pixel distances
- * @param {bigshot.Point3D} view the viewer position in world space
- */
- render : function render (world, scale, view) {
- var s = scale / (this.image.width - 1);
- var ps = scale * 1.0;
- var p = this.p;
- var u = this.u;
- var v = this.v;
-
- this.image.style.position = "absolute";
- if (!this.image.inWorld || this.image.inWorld != 1) {
- world.appendChild (this.image);
- }
- this.image.inWorld = 2;
- this.image.style.WebkitTransformOrigin = "0px 0px 0px";
- this.image.style.WebkitTransform =
- this.quadTransform ({
- x : (p.x + view.x) * ps,
- y : (-p.y + view.y) * ps,
- z : (p.z + view.z) * ps
- }, {
- x : u.x * s,
- y : -u.y * s,
- z : u.z * s
- }, {
- x : v.x * s,
- y : -v.y * s,
- z : v.z * s
- });
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a textured quad scene.
- *
- * @param {HTMLElement} world element used as container for
- * the world coordinate system.
- * @param {number} scale the scaling factor to use to avoid
- * numeric errors.
- * @param {bigshot.Point3D} view the 3d-coordinates of the viewer
- *
- * @class A scene consisting of a number of quads, all with
- * a unique texture. Used by the {@link bigshot.VRPanorama} to render the VR cube.
- *
- * @see bigshot.CSS3DTexturedQuad
- */
-bigshot.CSS3DTexturedQuadScene = function (world, scale, view) {
- this.quads = new Array ();
- this.world = world;
- this.scale = scale;
- this.view = view;
-}
-
-bigshot.CSS3DTexturedQuadScene.prototype = {
- /**
- * Adds a new quad to the scene.
- *
- * @param {bigshot.TexturedQuad} quad the quad to add to the scene
- */
- addQuad : function (quad) {
- this.quads.push (quad);
- },
-
- /**
- * Renders all quads.
- */
- render : function () {
- for (var i = 0; i < this.quads.length; ++i) {
- this.quads[i].render (this.world, this.scale, this.view);
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Abstract base for textured quad scenes.
- */
-bigshot.TexturedQuadScene = function () {
-}
-
-bigshot.TexturedQuadScene.prototype = {
- /**
- * Adds a quad to the scene.
- */
- addQuad : function (quad) {},
-
- /**
- * Renders the scene.
- */
- render : function () {}
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class WebGL renderer.
- */
-bigshot.WebGLVRRenderer = function (container) {
- this.container = container;
-
- this.canvas = document.createElement ("canvas");
- this.canvas.width = 480;
- this.canvas.height = 480;
- this.canvas.style.position = "absolute";
- this.container.appendChild (this.canvas);
-
- this.webGl = new bigshot.WebGL (this.canvas);
- this.webGl.initShaders ();
- this.webGl.gl.clearColor(0.0, 0.0, 0.0, 1.0);
- this.webGl.gl.blendFunc (this.webGl.gl.ONE, this.webGl.gl.ZERO);
- this.webGl.gl.enable (this.webGl.gl.BLEND);
- this.webGl.gl.disable (this.webGl.gl.DEPTH_TEST);
- this.webGl.gl.clearDepth (1.0);
-
- var that = this;
- this.buffers = new bigshot.TimedWeakReference (function () {
- return that.setupBuffers ();
- }, function (heldObject) {
- that.disposeBuffers (heldObject);
- }, 1000);
-}
-
-bigshot.WebGLVRRenderer.prototype = {
- createTileCache : function (onloaded, onCacheInit, parameters) {
- return new bigshot.TextureTileCache (onloaded, onCacheInit, parameters, this.webGl);
- },
-
- createTexturedQuadScene : function () {
- return new bigshot.WebGLTexturedQuadScene (this.webGl, this.buffers);
- },
-
- setupBuffers : function () {
- var vertexPositionBuffer = this.webGl.gl.createBuffer();
-
- var textureCoordBuffer = this.webGl.gl.createBuffer();
- this.webGl.gl.bindBuffer(this.webGl.gl.ARRAY_BUFFER, textureCoordBuffer);
- var textureCoords = [
- // Front face
- 0.0, 0.0,
- 1.0, 0.0,
- 1.0, 1.0,
- 0.0, 1.0
- ];
- this.webGl.gl.bufferData (this.webGl.gl.ARRAY_BUFFER, new Float32Array (textureCoords), this.webGl.gl.STATIC_DRAW);
-
- var vertexIndexBuffer = this.webGl.gl.createBuffer();
- this.webGl.gl.bindBuffer(this.webGl.gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
- var vertexIndexes = [
- 0, 2, 1,
- 0, 3, 2
- ];
- this.webGl.gl.bufferData(this.webGl.gl.ELEMENT_ARRAY_BUFFER, new Uint16Array (vertexIndexes), this.webGl.gl.STATIC_DRAW);
-
- this.webGl.gl.bindBuffer(this.webGl.gl.ARRAY_BUFFER, textureCoordBuffer);
- this.webGl.gl.vertexAttribPointer(this.webGl.shaderProgram.textureCoordAttribute, 2, this.webGl.gl.FLOAT, false, 0, 0);
-
- this.webGl.gl.bindBuffer(this.webGl.gl.ARRAY_BUFFER, vertexPositionBuffer);
- this.webGl.gl.vertexAttribPointer(this.webGl.shaderProgram.vertexPositionAttribute, 3, this.webGl.gl.FLOAT, false, 0, 0);
-
- return {
- vertexPositionBuffer : vertexPositionBuffer,
- textureCoordBuffer : textureCoordBuffer,
- vertexIndexBuffer : vertexIndexBuffer
- };
- },
-
- dispose : function () {
- this.buffers.dispose ();
- this.container.removeChild (this.canvas);
- delete this.canvas;
- this.webGl.dispose ();
- delete this.webGl;
- },
-
- disposeBuffers : function (buffers) {
- this.webGl.gl.deleteBuffer (buffers.vertexPositionBuffer);
- this.webGl.gl.deleteBuffer (buffers.vertexIndexBuffer);
- this.webGl.gl.deleteBuffer (buffers.textureCoordBuffer);
- },
-
- getElement : function () {
- return this.canvas;
- },
-
- supportsUpdate : function () {
- return false;
- },
-
- createTexturedQuad : function (p, u, v, texture) {
- return new bigshot.WebGLTexturedQuad (p, u, v, texture);
- },
-
- getViewportWidth : function () {
- return this.webGl.gl.viewportWidth;
- },
-
- getViewportHeight : function () {
- return this.webGl.gl.viewportHeight;
- },
-
- beginRender : function (rotation, fov, translation, rotationOffsets) {
- this.webGl.gl.viewport (0, 0, this.webGl.gl.viewportWidth, this.webGl.gl.viewportHeight);
-
- this.webGl.pMatrix.reset ();
- this.webGl.pMatrix.perspective (fov, this.webGl.gl.viewportWidth / this.webGl.gl.viewportHeight, 0.1, 100.0);
-
- this.webGl.mvMatrix.reset ();
- this.webGl.mvMatrix.translate (translation);
- this.webGl.mvMatrix.rotateZ (rotationOffsets.r);
- this.webGl.mvMatrix.rotateX (rotationOffsets.p);
- this.webGl.mvMatrix.rotateY (rotationOffsets.y);
- this.webGl.mvMatrix.rotateY (rotation.y);
- this.webGl.mvMatrix.rotateX (rotation.p);
-
- this.mvMatrix = this.webGl.mvMatrix;
- this.pMatrix = this.webGl.pMatrix;
- this.mvpMatrix = this.pMatrix.matrix ().multiply (this.mvMatrix.matrix ());
- },
-
- endRender : function () {
-
- },
-
- resize : function (w, h) {
- this.canvas.width = w;
- this.canvas.height = h;
- if (this.container.style.width != "") {
- this.container.style.width = w + "px";
- }
- if (this.container.style.height != "") {
- this.container.style.height = h + "px";
- }
- },
-
- onresize : function () {
- this.webGl.onresize ();
- }
-}
-
-bigshot.Object.extend (bigshot.WebGLVRRenderer, bigshot.AbstractVRRenderer);
-bigshot.Object.validate ("bigshot.WebGLVRRenderer", bigshot.VRRenderer);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * @class Abstract base for textured quads.
- */
-bigshot.TexturedQuad = function () {
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a textured quad object.
- *
- * @class An abstraction for textured quads. Used in the
- * {@link bigshot.WebGLTexturedQuadScene}.
- *
- * @param {bigshot.Point3D} p the top-left corner of the quad
- * @param {bigshot.Point3D} u vector pointing from p along the top edge of the quad
- * @param {bigshot.Point3D} v vector pointing from p along the left edge of the quad
- * @param {WebGLTexture} the texture to use.
- */
-bigshot.WebGLTexturedQuad = function (p, u, v, texture) {
- this.p = p;
- this.u = u;
- this.v = v;
- this.texture = texture;
-}
-
-bigshot.WebGLTexturedQuad.prototype = {
-
- /**
- * Renders the quad using the given {@link bigshot.WebGL} instance.
- * Currently creates, fills, draws with and then deletes three buffers -
- * not very efficient, but works.
- *
- * @param {bigshot.WebGL} webGl the WebGL wrapper instance to use for rendering.
- */
- render : function (webGl, vertexPositionBuffer, textureCoordBuffer, vertexIndexBuffer) {
- webGl.gl.bindBuffer(webGl.gl.ARRAY_BUFFER, vertexPositionBuffer);
- var vertices = [
- this.p.x, this.p.y, this.p.z,
- this.p.x + this.u.x, this.p.y + this.u.y, this.p.z + this.u.z,
- this.p.x + this.u.x + this.v.x, this.p.y + this.u.y + this.v.y, this.p.z + this.u.z + this.v.z,
- this.p.x + this.v.x, this.p.y + this.v.y, this.p.z + this.v.z
- ];
- webGl.gl.bufferData(webGl.gl.ARRAY_BUFFER, new Float32Array (vertices), webGl.gl.STATIC_DRAW);
-
- webGl.gl.activeTexture(webGl.gl.TEXTURE0);
- webGl.gl.bindTexture(webGl.gl.TEXTURE_2D, this.texture);
- webGl.gl.uniform1i(webGl.shaderProgram.samplerUniform, 0);
-
- webGl.gl.bindBuffer(webGl.gl.ELEMENT_ARRAY_BUFFER, vertexIndexBuffer);
- webGl.gl.drawElements(webGl.gl.TRIANGLES, 6, webGl.gl.UNSIGNED_SHORT, 0);
-
- webGl.gl.bindTexture(webGl.gl.TEXTURE_2D, null);
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a textured quad scene.
- *
- * @param {bigshot.WebGL} webGl the webGl instance to use for rendering.
- *
- * @class A "scene" consisting of a number of quads, all with
- * a unique texture. Used by the {@link bigshot.VRPanorama} to render the VR cube.
- *
- * @see bigshot.WebGLTexturedQuad
- */
-bigshot.WebGLTexturedQuadScene = function (webGl, buffers) {
- this.quads = new Array ();
- this.webGl = webGl;
- this.buffers = buffers;
-}
-
-bigshot.WebGLTexturedQuadScene.prototype = {
- /**
- * Adds a new quad to the scene.
- */
- addQuad : function (quad) {
- this.quads.push (quad);
- },
-
- /**
- * Renders all quads.
- */
- render : function () {
- var b = this.buffers.get ();
- var vertexPositionBuffer = b.vertexPositionBuffer;
- var textureCoordBuffer = b.textureCoordBuffer;
- var vertexIndexBuffer = b.vertexIndexBuffer;
-
- this.webGl.setMatrixUniforms();
-
- for (var i = 0; i < this.quads.length; ++i) {
- this.quads[i].render (this.webGl, vertexPositionBuffer, textureCoordBuffer, vertexIndexBuffer);
- }
- }
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new VR panorama parameter object and populates it with default values for
- * all values not explicitly given.
- *
- * @class VRPanoramaParameters parameter object.
- * You need not set any fields that can be read from the image descriptor that
- * MakeImagePyramid creates. See the {@link bigshot.VRPanorama}
- * documentation for required parameters.
- *
- * <p>Usage:
- *
- * @example
- * var bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * basePath : "/bigshot.php?file=myvr.bigshot",
- * fileSystemType : "archive",
- * container : document.getElementById ("bigshot_canvas")
- * }));
- * @param values named parameter map, see the fields below for parameter names and types.
- * @see bigshot.VRPanorama
- */
-bigshot.VRPanoramaParameters = function (values) {
- /**
- * Size of low resolution preview image along the longest image
- * dimension. The preview is assumed to have the same aspect
- * ratio as the full image (specified by width and height).
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type int
- * @public
- */
- this.posterSize = 0;
-
- /**
- * Url for the image tile to show while the tile is loading and no
- * low-resolution preview is available.
- *
- * @default <code>null</code>, which results in an all-black image
- * @type String
- * @public
- */
- this.emptyImage = null;
-
- /**
- * Suffix to append to the tile filenames. Typically <code>".jpg"</code> or
- * <code>".png"</code>.
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type String
- */
- this.suffix = null;
-
- /**
- * The width of the full image; in pixels.
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.width = 0;
-
- /**
- * The height of the full image; in pixels.
- *
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- * @type int
- */
- this.height = 0;
-
- /**
- * For {@link bigshot.VRPanorama}, the {@code div} to render into.
- *
- * @type HTMLDivElement
- */
- this.container = null;
-
- /**
- * The maximum number of times to split a cube face into four quads.
- *
- * @type int
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- */
- this.maxTesselation = -1;
-
- /**
- * Size of one tile in pixels.
- *
- * @type int
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- */
- this.tileSize = 0;
-
- /**
- * Tile overlap. Not implemented.
- *
- * @type int
- * @default <i>Optional</i> set by MakeImagePyramid and loaded from descriptor
- */
- this.overlap = 0;
-
- /**
- * Base path for the image. This is filesystem dependent; but for the two most common cases
- * the following should be set
- *
- * <ul>
- * <li><b>archive</b>= The basePath is <code>"&lt;path&gt;/bigshot.php?file=&lt;path-to-bigshot-archive-relative-to-bigshot.php&gt;"</code>;
- * for example; <code>"/bigshot.php?file=images/bigshot-sample.bigshot"</code>.
- * <li><b>folder</b>= The basePath is <code>"&lt;path-to-image-folder&gt;"</code>;
- * for example; <code>"/images/bigshot-sample"</code>.
- * </ul>
- *
- * @type String
- */
- this.basePath = null;
-
- /**
- * The file system type. Used to create a filesystem instance unless
- * the fileSystem field is set. Possible values are <code>"archive"</code>,
- * <code>"folder"</code> or <code>"dzi"</code>.
- *
- * @type String
- * @default "folder"
- */
- this.fileSystemType = "folder";
-
- /**
- * A reference to a filesystem implementation. If set; it overrides the
- * fileSystemType field.
- *
- * @default set depending on value of bigshot.VRPanoramaParameters#fileSystemType
- * @type bigshot.FileSystem
- */
- this.fileSystem = null;
-
- /**
- * Object used to load data files.
- *
- * @default bigshot.DefaultDataLoader
- * @type bigshot.DataLoader
- */
- this.dataLoader = new bigshot.DefaultDataLoader ();
-
- /**
- * The maximum magnification for the texture tiles making up the VR cube.
- * Used for level-of-detail tesselation.
- * A value of 1.0 means that textures will never be stretched (one texture pixel will
- * always be at most one screen pixel), unless there is no more detailed texture available.
- * A value of 2.0 means that textures may be stretched at most 2x (one texture pixel
- * will always be at most 2x2 screen pixels)
- * The bigger the value, the less texture data is required, but quality suffers.
- *
- * @type number
- * @default 1.0
- */
- this.maxTextureMagnification = 1.0;
-
- /**
- * The WebGL texture filter to use for magnifying textures.
- * Possible values are all values valid for <code>TEXTURE_MAG_FILTER</code>.
- * <code>null</code> means <code>NEAREST</code>.
- *
- * @default null / NEAREST.
- */
- this.textureMagFilter = null;
-
- /**
- * The WebGL texture filter to use for supersampling (minifying) textures.
- * Possible values are all values valid for <code>TEXTURE_MIN_FILTER</code>.
- * <code>null</code> means <code>NEAREST</code>.
- *
- * @default null / NEAREST.
- */
- this.textureMinFilter = null;
-
- /**
- * Minimum vertical field of view in degrees.
- *
- * @default 2.0
- * @type number
- */
- this.minFov = 2.0;
-
- /**
- * Maximum vertical field of view in degrees.
- *
- * @default 90.0
- * @type number
- */
- this.maxFov = 90;
-
- /**
- * Minimum pitch in degrees.
- *
- * @default -90
- * @type number
- */
- this.minPitch = -90;
-
- /**
- * Maximum pitch in degrees.
- *
- * @default 90.0
- * @type number
- */
- this.maxPitch = 90;
-
- /**
- * Minimum yaw in degrees. The number is interpreted modulo 360.
- * The default value, -360, is just to make sure that we won't accidentally
- * trip it. If the number is set to something in the interval 0-360,
- * the autoRotate function will pan back and forth.
- *
- * @default -360
- * @type number
- */
- this.minYaw = -360;
-
- /**
- * Maximum yaw in degrees. The number is interpreted modulo 360.
- * The default value, 720, is just to make sure that we won't accidentally
- * trip it. If the number is set to something in the interval 0-360,
- * the autoRotate function will pan back and forth.
- *
- * @default 720.0
- * @type number
- */
- this.maxYaw = 720;
-
- /**
- * Transform offset for yaw.
- * @default 0.0
- * @type number
- */
- this.yawOffset = 0.0;
-
- /**
- * Transform offset for pitch.
- * @default 0.0
- * @type number
- */
- this.pitchOffset = 0.0;
-
- /**
- * Transform offset for roll.
- * @default 0.0
- * @type number
- */
- this.rollOffset = 0.0;
-
- /**
- * Function to call when all six cube faces have loaded the base texture level
- * and can be rendered.
- *
- * @type function()
- * @default null
- */
- this.onload = null;
-
- /**
- * The rendering back end to use.
- * Values are "css" and "webgl".
- *
- * @type String
- * @default null
- */
- this.renderer = null;
-
- /**
- * Controls whether the panorama can be "flung" by quickly dragging and releasing.
- *
- * @type boolean
- * @default true
- */
- this.fling = true;
-
- /**
- * Controls the decay of the "flinging" animation. The fling animation decays
- * as 2^(-flingScale * t) where t is the time in milliseconds since the animation started.
- * For the animation to decay to half-speed in X seconds,
- * flingScale should then be set to 1 / (X*1000).
- *
- * @type float
- * @default 0.004
- */
- this.flingScale = 0.004;
-
- if (values) {
- for (var k in values) {
- this[k] = values[k];
- }
- }
-
- this.merge = function (values, overwrite) {
- for (var k in values) {
- if (overwrite || !this[k]) {
- this[k] = values[k];
- }
- }
- }
- return this;
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new VR panorama in a canvas. <b>Requires WebGL or CSS3D support.</b>
- * (Note: See {@link bigshot.VRPanorama#dispose} for important information.)
- *
- * <h3 id="creating-a-cubemap">Creating a Cube Map</h3>
- *
- * <p>The panorama consists of six image pyramids, one for each face of the VR cube.
- * Due to restrictions in WebGL, each texture tile must have a power-of-two (POT) size -
- * that is, 2, 4, ..., 128, 256, etc. Furthermore, due to the way the faces are tesselated
- * the largest image must consist of POT x POT tiles. The final restriction is that the
- * tiles must overlap for good seamless results.
- *
- * <p>The MakeImagePyramid has some sensible defaults built-in. If you just use the
- * command line:
- *
- * <code><pre>
- * java -jar bigshot.jar input.jpg temp/dzi \
- * --preset dzi-cubemap \
- * --format folders
- * </pre></code>
- *
- * <p>You will get 2034 pixels per face, and a tile size of 256 pixels with 2 pixels
- * overlap. If you don't like that, you can use the <code>overlap</code>, <code>face-size</code>
- * and <code>tile-size</code> parameters. Let's take these one by one:
- *
- * <ul>
- * <li><p><code>overlap</code>: Overlap defines how much tiles should overlap, just to avoid
- * seams in the rendered results caused by finite numeric precision. The default is <b>2</b>, which
- * I've found works great for me.</p></li>
- * <li><p><code>tile-size</code>: First you need to decide what POT size the output should be.
- * Then subtract the overlap value. For example, if you set overlap to 1, <code>tile-size</code>
- * could be 127, 255, 511, or any 2<sup>n</sup>-1 value.</p></li>
- * <li><p><code>face-size</code>: Finally, we decide on a size for the full cube face. This should be
- * tile-size * 2<sup>n</sup>. Let's say we set n=3, which makes each face 8x8 tiles at the most zoomed-in
- * level. For a tile-size of 255, then, face-size is 255*2<sup>3</sup> = 255*8 = <b>2040</b>.</p></li>
- * </ul>
- *
- * <p>A command line for the hypothetical scenario above would be:
- *
- * <code><pre>
- * java -jar bigshot.jar input.jpg temp/dzi \
- * --preset dzi-cubemap \
- * --overlap 1 \
- * --tile-size 255 \
- * --face-size 2040 \
- * --format folders
- * </pre></code>
- *
- * <p>If your tile size numbers don't add up, you'll get a warning like:
- *
- * <code><pre>
- * WARNING: Resulting image tile size (tile-size + overlap) is not a power of two: 255
- * </pre></code>
- *
- * <p>If your face size don't add up, you'll get another warning:
- *
- * <code><pre>
- * WARNING: face-size is not an even multiple of tile-size: 2040 % 254 != 0
- * </pre></code>
- *
- * <h3 id="integration-with-saladoplayer">Integration With SaladoPlayer</h3>
- *
- * <p><a href="http://panozona.com/wiki/">SaladoPlayer</a> is a cool
- * Flash-based VR panorama viewer that can display Deep Zoom Images.
- * It can be used as a fallback for Bigshot for browsers that don't
- * support WebGL.
- *
- * <p>Since Bigshot can use a Deep Zoom Image (DZI) via a {@link bigshot.DeepZoomImageFileSystem}
- * adapter, the common file format is DZI. There are two cases: The first is
- * when the DZI is served up as a folder structure, the second when
- * we pack the DZI into a Bigshot archive and serve it using bigshot.php.
- *
- * <h4>Serving DZI as Folders</h4>
- *
- * <p>This is an easy one. First, we generate the required DZIs:
- *
- * <code><pre>
- * java -jar bigshot.jar input.jpg temp/dzi \
- * --preset dzi-cubemap \
- * --format folders
- * </pre></code>
- *
- * <p>We'll assume that we have the six DZI folders in "temp/dzi", and that
- * they have "face_" as a common prefix (which is what Bigshot's MakeImagePyramid
- * outputs). So we have, for example, "temp/dzi/face_f.xml" and the tiles for face_f
- * in "temp/dzi/face_f/". Set up Bigshot like this:
- *
- * <code><pre>
- * bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * container : document.getElementById ("canvas"),
- * basePath : "temp/dzi",
- * fileSystemType : "dzi"
- * }));
- * </pre></code>
- *
- * <p>SaladoPlayer uses an XML config file, which in this case will
- * look something like this:
- *
- * <code><pre>
- * &lt;SaladoPlayer>
- * &lt;global debug="false" firstPanorama="pano"/>
- * &lt;panoramas>
- * &lt;panorama id="pano" path="temp/dzi/face_f.xml"/>
- * &lt;/panoramas>
- * &lt;/SaladoPlayer>
- * </pre></code>
- *
- * <h4>Serving DZI as Archive</h4>
- *
- * <p>This one is a bit more difficult. First we create a DZI as a bigshot archive:
- *
- * <code><pre>
- * java -jar bigshot.jar input.jpg temp/dzi.bigshot \
- * --preset dzi-cubemap \
- * --format archive
- * </pre></code>
- *
- * <p>We'll assume that we have our Bigshot archive at
- * "temp/dzi.bigshot". For this we will use the "entry" parameter of bigshot.php
- * to serve up the right files:
- *
- * <code><pre>
- * bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * container : document.getElementById ("canvas"),
- * basePath : "/bigshot.php?file=temp/dzi.bigshot&entry=",
- * fileSystemType : "dzi"
- * }));
- * </pre></code>
- *
- * <p>SaladoPlayer uses an XML config file, which in this case will
- * look something like this:
- *
- * <code><pre>
- * &lt;SaladoPlayer>
- * &lt;global debug="false" firstPanorama="pano"/>
- * &lt;panoramas>
- * &lt;panorama id="pano" path="/bigshot.php?file=dzi.bigshot&amp;amp;entry=face_f.xml"/>
- * &lt;/panoramas>
- * &lt;/SaladoPlayer>
- * </pre></code>
- *
- * <h3>Usage example:</h3>
- * @example
- * var bvr = new bigshot.VRPanorama (
- * new bigshot.VRPanoramaParameters ({
- * basePath : "/bigshot.php?file=myvr.bigshot",
- * fileSystemType : "archive",
- * container : document.getElementById ("bigshot_canvas")
- * }));
- * @class A cube-map VR panorama.
- * @extends bigshot.EventDispatcher
- *
- * @param {bigshot.VRPanoramaParameters} parameters the panorama parameters.
- *
- * @see bigshot.VRPanoramaParameters
- */
-bigshot.VRPanorama = function (parameters) {
- bigshot.EventDispatcher.call (this);
-
- var that = this;
-
- this.parameters = parameters;
- this.maxTextureMagnification = parameters.maxTextureMagnification;
- this.container = parameters.container;
- this.browser = new bigshot.Browser ();
- this.dragStart = null;
- this.dragDistance = 0;
- this.hotspots = [];
- this.disposed = false;
-
- this.transformOffsets = {
- y : parameters.yawOffset,
- p : parameters.pitchOffset,
- r : parameters.rollOffset
- };
-
- /**
- * Current camera state.
- * @private
- */
- this.state = {
- rotation : {
- /**
- * Pitch in degrees.
- * @type float
- * @private
- */
- p : 0.0,
-
- /**
- * Yaw in degrees.
- * @type float
- * @private
- */
- y : 0.0,
-
- r : 0
- },
-
- /**
- * Field of view (vertical) in degrees.
- * @type float
- * @private
- */
- fov : 45,
-
- translation : {
- /**
- * Translation along X-axis.
- * @private
- * @type float
- */
- x : 0.0,
-
- /**
- * Translation along Y-axis.
- * @private
- * @type float
- */
- y : 0.0,
-
- /**
- * Translation along Z-axis.
- * @private
- * @type float
- */
- z : 0.0
- }
- };
-
- /**
- * Renderer wrapper.
- * @private
- * @type bigshot.VRRenderer
- */
- this.renderer = null;
- if (this.parameters.renderer) {
- if (this.parameters.renderer == "css") {
- this.renderer = new bigshot.CSS3DVRRenderer (this.container);
- } else if (this.parameters.renderer == "webgl") {
- this.renderer = new bigshot.WebGLVRRenderer (this.container)
- } else {
- throw new Error ("Unknown renderer: " + this.parameters.renderer);
- }
- } else {
- this.renderer =
- bigshot.WebGLUtil.isWebGLSupported () ?
- new bigshot.WebGLVRRenderer (this.container)
- :
- new bigshot.CSS3DVRRenderer (this.container);
- }
-
- /**
- * List of render listeners to call at the start and end of each render.
- *
- * @private
- */
- this.renderListeners = new Array ();
-
- this.renderables = new Array ();
-
- /**
- * Current value of the idle counter.
- *
- * @private
- */
- this.idleCounter = 0;
-
- /**
- * Maximum value of the idle counter before any idle events start,
- * such as autorotation.
- *
- * @private
- */
- this.maxIdleCounter = -1;
-
-
- /**
- * Integer acting as a "permit". When the smoothRotate function
- * is called, the current value is incremented and saved. If the number changes
- * that particular call to smoothRotate stops. This way we avoid
- * having multiple smoothRotate rotations going in parallel.
- * @private
- * @type int
- */
- this.smoothrotatePermit = 0;
-
- /**
- * Helper function to consume events.
- * @private
- */
- var consumeEvent = function (event) {
- if (event.preventDefault) {
- event.preventDefault ();
- }
- return false;
- };
-
- /**
- * Full screen handler.
- *
- * @private
- */
- this.fullScreenHandler = null;
-
- this.renderAsapPermitTaken = false;
-
- /**
- * An element to use as reference when resizing the canvas element.
- * If non-null, any onresize() calls will result in the canvas being
- * resized to the size of this element.
- *
- * @private
- */
- this.sizeContainer = null;
-
- /**
- * The six cube faces.
- *
- * @type bigshot.VRFace[]
- * @private
- */
- var facesInit = {
- facesLeft : 6,
- faceLoaded : function () {
- this.facesLeft--;
- if (this.facesLeft == 0) {
- if (that.parameters.onload) {
- that.parameters.onload ();
- }
- }
- }
- };
- var onFaceLoad = function () {
- facesInit.faceLoaded ()
- };
-
- this.vrFaces = new Array ();
- this.vrFaces[0] = new bigshot.VRFace (this, "f", {x:-1, y:1, z:-1}, 2.0, {x:1, y:0, z:0}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[1] = new bigshot.VRFace (this, "b", {x:1, y:1, z:1}, 2.0, {x:-1, y:0, z:0}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[2] = new bigshot.VRFace (this, "l", {x:-1, y:1, z:1}, 2.0, {x:0, y:0, z:-1}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[3] = new bigshot.VRFace (this, "r", {x:1, y:1, z:-1}, 2.0, {x:0, y:0, z:1}, {x:0, y:-1, z:0}, onFaceLoad);
- this.vrFaces[4] = new bigshot.VRFace (this, "u", {x:-1, y:1, z:1}, 2.0, {x:1, y:0, z:0}, {x:0, y:0, z:-1}, onFaceLoad);
- this.vrFaces[5] = new bigshot.VRFace (this, "d", {x:-1, y:-1, z:-1}, 2.0, {x:1, y:0, z:0}, {x:0, y:0, z:1}, onFaceLoad);
-
- /**
- * Helper function to translate touch events to mouse-like events.
- * @private
- */
- var translateEvent = function (event) {
- if (event.clientX) {
- return event;
- } else {
- return {
- clientX : event.changedTouches[0].clientX,
- clientY : event.changedTouches[0].clientY
- };
- };
- };
-
- this.lastTouchStartAt = -1;
-
- this.allListeners = {
- "mousedown" : function (e) {
- that.smoothRotate ();
- that.resetIdle ();
- that.dragMouseDown (e);
- return consumeEvent (e);
- },
- "mouseup" : function (e) {
- that.resetIdle ();
- that.dragMouseUp (e);
- return consumeEvent (e);
- },
- "mousemove" : function (e) {
- that.resetIdle ();
- that.dragMouseMove (e);
- return consumeEvent (e);
- },
- "gesturestart" : function (e) {
- that.gestureStart (e);
- return consumeEvent (e);
- },
- "gesturechange" : function (e) {
- that.gestureChange (e);
- return consumeEvent (e);
- },
- "gestureend" : function (e) {
- that.gestureEnd (e);
- return consumeEvent (e);
- },
-
- "DOMMouseScroll" : function (e) {
- that.resetIdle ();
- that.mouseWheel (e);
- return consumeEvent (e);
- },
- "mousewheel" : function (e) {
- that.resetIdle ();
- that.mouseWheel (e);
- return consumeEvent (e);
- },
- "dblclick" : function (e) {
- that.mouseDoubleClick (e);
- return consumeEvent (e);
- },
-
- "touchstart" : function (e) {
- that.smoothRotate ();
- that.lastTouchStartAt = new Date ().getTime ();
- that.resetIdle ();
- that.dragMouseDown (translateEvent (e));
- return consumeEvent (e);
- },
- "touchend" : function (e) {
- that.resetIdle ();
- var handled = that.dragMouseUp (translateEvent (e));
- if (!handled && (that.lastTouchStartAt > new Date().getTime() - 350)) {
- that.mouseDoubleClick (translateEvent (e));
- }
- that.lastTouchStartAt = -1;
- return consumeEvent (e);
- },
- "touchmove" : function (e) {
- if (that.dragDistance > 24) {
- that.lastTouchStartAt = -1;
- }
- that.resetIdle ();
- that.dragMouseMove (translateEvent (e));
- return consumeEvent (e);
- }
- };
- this.addEventListeners ();
-
- /**
- * Stub function to call onresize on this instance.
- *
- * @private
- */
- this.onresizeHandler = function (e) {
- that.onresize ();
- };
-
- this.browser.registerListener (window, 'resize', this.onresizeHandler, false);
- this.browser.registerListener (document.body, 'orientationchange', this.onresizeHandler, false);
-
- this.setPitch (0.0);
- this.setYaw (0.0);
- this.setFov (45.0);
-}
-
-/*
- * Statics
- */
-
-/**
- * When the mouse is pressed and dragged, the camera rotates
- * proportionally to the length of the dragging.
- *
- * @constant
- * @public
- * @static
- */
-bigshot.VRPanorama.DRAG_GRAB = "grab";
-
-/**
- * When the mouse is pressed and dragged, the camera continuously
- * rotates with a speed that is proportional to the length of the
- * dragging.
- *
- * @constant
- * @public
- * @static
- */
-bigshot.VRPanorama.DRAG_PAN = "pan";
-
-/**
- * @name bigshot.VRPanorama.RenderState
- * @class The state the renderer is in when a {@link bigshot.VRPanorama.RenderListener} is called.
- *
- * @see bigshot.VRPanorama.ONRENDER_BEGIN
- * @see bigshot.VRPanorama.ONRENDER_END
- */
-
-/**
- * A RenderListener state parameter value used at the start of each render.
- *
- * @constant
- * @public
- * @static
- * @type bigshot.VRPanorama.RenderState
- */
-bigshot.VRPanorama.ONRENDER_BEGIN = 0;
-
-/**
- * A RenderListener state parameter value used at the end of each render.
- *
- * @constant
- * @public
- * @static
- * @type bigshot.VRPanorama.RenderState
- */
-bigshot.VRPanorama.ONRENDER_END = 1;
-
-/**
- * A RenderListener cause parameter indicating that a previously requested
- * texture has loaded and a render is forced. The data parameter is not used.
- *
- * @constant
- * @public
- * @static
- * @param {bigshot.VRPanorama.RenderCause}
- */
-bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE = 0;
-
-/**
- * @name bigshot.VRPanorama.RenderCause
- * @class The reason why the {@link bigshot.VRPanorama} is being rendered.
- * Due to the events outside of the panorama, the VR panorama may be forced to
- * re-render itself. When this happens, the {@link bigshot.VRPanorama.RenderListener}s
- * receive a constant indicating the cause of the rendering.
- *
- * @see bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE
- */
-
-/**
- * Specification for functions passed to {@link bigshot.VRPanorama#addRenderListener}.
- *
- * @name bigshot.VRPanorama.RenderListener
- * @function
- * @param {bigshot.VRPanorama.RenderState} state The state of the renderer. Can be {@link bigshot.VRPanorama.ONRENDER_BEGIN} or {@link bigshot.VRPanorama.ONRENDER_END}
- * @param {bigshot.VRPanorama.RenderCause} [cause] The reason for rendering the scene. Can be undefined or {@link bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE}
- * @param {Object} [data] An optional data object that is dependent on the cause. See the documentation
- * for the different causes.
- */
-
-/**
- * Specification for functions passed to {@link bigshot.VRPanorama#addRenderable}.
- *
- * @name bigshot.VRPanorama.Renderable
- * @function
- * @param {bigshot.VRRenderer} renderer The renderer object to use.
- * @param {bigshot.TexturedQuadScene} scene The scene to render into.
- */
-
-/** */
-bigshot.VRPanorama.prototype = {
- /**
- * Adds a hotstpot.
- *
- * @param {bigshot.VRHotspot} hs the hotspot to add
- */
- addHotspot : function (hs) {
- this.hotspots.push (hs);
- },
-
- /**
- * Returns the {@link bigshot.VRPanoramaParameters} object used by this instance.
- *
- * @type bigshot.VRPanoramaParameters
- */
- getParameters : function () {
- return this.parameters;
- },
-
- /**
- * Sets the view translation.
- *
- * @param x translation of the viewer along the X axis
- * @param y translation of the viewer along the Y axis
- * @param z translation of the viewer along the Z axis
- */
- setTranslation : function (x, y, z) {
- this.state.translation.x = x;
- this.state.translation.y = y;
- this.state.translation.z = z;
- },
-
- /**
- * Returns the current view translation as an x-y-z triplet.
- *
- * @returns {number} x translation of the viewer along the X axis
- * @returns {number} y translation of the viewer along the Y axis
- * @returns {number} z translation of the viewer along the Z axis
- */
- getTranslation : function () {
- return this.state.translation;
- },
-
- /**
- * Sets the field of view.
- *
- * @param {number} fov the vertical field of view, in degrees
- */
- setFov : function (fov) {
- fov = Math.min (this.parameters.maxFov, fov);
- fov = Math.max (this.parameters.minFov, fov);
- this.state.fov = fov;
- },
-
- /**
- * Gets the field of view.
- *
- * @return {number} the vertical field of view, in degrees
- */
- getFov : function () {
- return this.state.fov;
- },
-
- /**
- * Returns the angle (yaw, pitch) for a given pixel coordinate.
- *
- * @param {number} x the x-coordinate of the pixel, measured in pixels
- * from the left edge of the panorama.
- * @param {number} y the y-coordinate of the pixel, measured in pixels
- * from the top edge of the panorama.
- * @return {number} .yaw the yaw angle of the pixel (0 &lt;= yaw &lt; 360)
- * @return {number} .pitch the pitch angle of the pixel (-180 &lt;= pitch &lt;= 180)
- *
- * @example
- * var container = ...; // an HTML element
- * var pano = ...; // a bigshot.VRPanorama
- * ...
- * container.addEventListener ("click", function (e) {
- * var clickX = e.clientX - container.offsetX;
- * var clickY = e.clientY - container.offsetY;
- * var polar = pano.screenToPolar (clickX, clickY);
- * alert ("You clicked at: " +
- * "Yaw: " + polar.yaw +
- * " Pitch: " + polar.pitch);
- * });
- */
- screenToPolar : function (x, y) {
- var dray = this.screenToRayDelta (x, y);
- var ray = $V([dray.x, dray.y, dray.z, 1.0]);
-
- ray = Matrix.RotationX (this.getPitch () * Math.PI / 180.0).ensure4x4 ().x (ray);
- ray = Matrix.RotationY (-this.getYaw () * Math.PI / 180.0).ensure4x4 ().x (ray);
-
- var dx = ray.e(1);
- var dy = ray.e(2);
- var dz = ray.e(3);
-
- var dxz = Math.sqrt (dx * dx + dz * dz);
-
- var dyaw = Math.atan2 (dx, -dz) * 180 / Math.PI;
- var dpitch = Math.atan2 (dy, dxz) * 180 / Math.PI;
-
- var res = {};
- res.yaw = (dyaw + 360) % 360.0;
- res.pitch = dpitch;
-
- return res;
- },
-
- /**
- * Restricts the pitch value to be between the minPitch and maxPitch parameters.
- *
- * @param {number} p the pitch value
- * @returns the constrained pitch value.
- */
- snapPitch : function (p) {
- p = Math.min (this.parameters.maxPitch, p);
- p = Math.max (this.parameters.minPitch, p);
- return p;
- },
-
- /**
- * Sets the current camera pitch.
- *
- * @param {number} p the pitch, in degrees
- */
- setPitch : function (p) {
- this.state.rotation.p = this.snapPitch (p);
- },
-
- /**
- * Subtraction mod 360, sort of...
- *
- * @private
- * @returns the angular distance with smallest magnitude to add to p0 to get to p1 % 360
- */
- circleDistance : function (p0, p1) {
- if (p1 > p0) {
- // p1 is somewhere clockwise to p0
- var d1 = (p1 - p0); // move clockwise
- var d2 = ((p1 - 360) - p0); // move counterclockwise, first -p0 to get to 0, then p1 - 360.
- return Math.abs (d1) < Math.abs (d2) ? d1 : d2;
- } else {
- // p1 is somewhere counterclockwise to p0
- var d1 = (p1 - p0); // move counterclockwise
- var d2 = (360 - p0) + p1; // move clockwise, first (360-p= to get to 0, then another p1 degrees
- return Math.abs (d1) < Math.abs (d2) ? d1 : d2;
- }
- },
-
- /**
- * Subtraction mod 360, sort of...
- *
- * @private
- */
- circleSnapTo : function (p, p1, p2) {
- var d1 = this.circleDistance (p, p1);
- var d2 = this.circleDistance (p, p2);
- return Math.abs (d1) < Math.abs (d2) ? p1 : p2;
- },
-
- /**
- * Constrains a yaw value to the required minimum and maximum values.
- *
- * @private
- */
- snapYaw : function (y) {
- y %= 360;
- if (y < 0) {
- y += 360;
- }
- if (this.parameters.minYaw < this.parameters.maxYaw) {
- if (y > this.parameters.maxYaw || y < this.parameters.minYaw) {
- y = circleSnapTo (y, this.parameters.minYaw, this.parameters.maxYaw);
- }
- } else {
- // The only time when minYaw > maxYaw is when the interval
- // contains the 0 angle.
- if (y > this.parameters.minYaw) {
- // ok, we're somewhere between minYaw and 0.0
- } else if (y > this.parameters.maxYaw) {
- // we're somewhere between maxYaw and minYaw
- // (but on the wrong side).
- // figure out the nearest point and snap to it
- y = circleSnapTo (y, this.parameters.minYaw, this.parameters.maxYaw);
- } else {
- // ok, we're somewhere between 0.0 and maxYaw
- }
- }
- return y;
- },
-
- /**
- * Sets the current camera yaw. The yaw is normalized between
- * 0 <= y < 360.
- *
- * @param {number} y the yaw, in degrees
- */
- setYaw : function (y) {
- this.state.rotation.y = this.snapYaw (y);
- },
-
- /**
- * Gets the current camera yaw.
- *
- * @return {number} the yaw, in degrees
- */
- getYaw : function () {
- return this.state.rotation.y;
- },
-
- /**
- * Gets the current camera pitch.
- *
- * @return {number} the pitch, in degrees
- */
- getPitch : function () {
- return this.state.rotation.p;
- },
-
- /**
- * Unregisters event handlers and other page-level hooks. The client need not call this
- * method unless bigshot images are created and removed from the page
- * dynamically. In that case, this method must be called when the client wishes to
- * free the resources allocated by the image. Otherwise the browser will garbage-collect
- * all resources automatically.
- * @public
- */
- dispose : function () {
- this.disposed = true;
- this.browser.unregisterListener (window, "resize", this.onresizeHandler, false);
- this.browser.unregisterListener (document.body, "orientationchange", this.onresizeHandler, false);
- this.removeEventListeners ();
-
- for (var i = 0; i < this.vrFaces.length; ++i) {
- this.vrFaces[i].dispose ();
- }
- this.renderer.dispose ();
- },
-
- /**
- * Creates and initializes a {@link bigshot.VREvent} object.
- * The {@link bigshot.VREvent#ray}, {@link bigshot.VREvent#yaw},
- * {@link bigshot.VREvent#pitch}, {@link bigshot.Event#target} and
- * {@link bigshot.Event#currentTarget} fields are set.
- *
- * @param {Object} data the data object for the event
- * @param {number} data.clientX the client x-coordinate of the event
- * @param {number} data.clientY the client y-coordinate of the event
- * @returns the new event object
- * @type bigshot.VREvent
- */
- createVREventData : function (data) {
- var elementPos = this.browser.getElementPosition (this.container);
- data.localX = data.clientX - elementPos.x;
- data.localY = data.clientY - elementPos.y;
-
- data.ray = this.screenToRay (data.localX, data.localY);
-
- var polar = this.screenToPolar (data.localX, data.localY);
- data.yaw = polar.yaw;
- data.pitch = polar.pitch;
- data.target = this;
- data.currentTarget = this;
-
- return new bigshot.VREvent (data);
- },
-
-
- /**
- * Sets up transformation matrices etc. Calls all render listeners with a state parameter
- * of {@link bigshot.VRPanorama.ONRENDER_BEGIN}.
- *
- * @private
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- beginRender : function (cause, data) {
- this.onrender (bigshot.VRPanorama.ONRENDER_BEGIN, cause, data);
- this.renderer.beginRender (this.state.rotation, this.state.fov, this.state.translation, this.transformOffsets);
- },
-
-
- /**
- * Add a function that will be called at various times during the render.
- *
- * @param {bigshot.VRPanorama.RenderListener} listener the listener function
- */
- addRenderListener : function (listener) {
- var rl = new Array ();
- rl = rl.concat (this.renderListeners);
- rl.push (listener);
- this.renderListeners = rl;
- },
-
- /**
- * Removes a function that will be called at various times during the render.
- *
- * @param {bigshot.VRPanorama.RenderListener} listener the listener function
- */
- removeRenderListener : function (listener) {
- var rl = new Array ();
- rl = rl.concat (this.renderListeners);
- for (var i = 0; i < rl.length; ++i) {
- if (rl[i] === listener) {
- rl.splice (i, 1);
- break;
- }
- }
- this.renderListeners = rl;
- },
-
- /**
- * Called at the start and end of every render.
- *
- * @event
- * @private
- * @type function()
- * @param {bigshot.VRPanorama.RenderState} state the current render state
- */
- onrender : function (state, cause, data) {
- var rl = this.renderListeners;
- for (var i = 0; i < rl.length; ++i) {
- rl[i](state, cause, data);
- }
- },
-
- /**
- * Performs per-render cleanup. Calls all render listeners with a state parameter
- * of {@link bigshot.VRPanorama.ONRENDER_END}.
- *
- * @private
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- endRender : function (cause, data) {
- for (var f in this.vrFaces) {
- this.vrFaces[f].endRender ();
- }
- this.renderer.endRender ();
- this.onrender (bigshot.VRPanorama.ONRENDER_END, cause, data);
- },
-
- /**
- * Add a function that will be called to render any additional quads.
- *
- * @param {bigshot.VRPanorama.Renderable} renderable The renderable, a function responsible for
- * rendering additional scene elements.
- */
- addRenderable : function (renderable) {
- var rl = new Array ();
- rl.concat (this.renderables);
- rl.push (renderable);
- this.renderables = rl;
- },
-
- /**
- * Removes a function that will be called to render any additional quads.
- *
- * @param {bigshot.VRPanorama.Renderable} renderable The renderable added using
- * {@link bigshot.VRPanorama#addRenderable}.
- */
- removeRenderable : function (renderable) {
- var rl = new Array ();
- rl.concat (this.renderables);
- for (var i = 0; i < rl.length; ++i) {
- if (rl[i] == listener) {
- rl.splice (i, 1);
- break;
- }
- }
- this.renderables = rl;
- },
-
- /**
- * Renders the VR cube.
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- render : function (cause, data) {
- if (!this.disposed) {
- this.beginRender (cause, data);
-
- var scene = this.renderer.createTexturedQuadScene ();
-
- for (var f in this.vrFaces) {
- this.vrFaces[f].render (scene);
- }
-
- for (var i = 0; i < this.renderables.length; ++i) {
- this.renderables[i](this.renderer, scene);
- }
-
- scene.render ();
-
- for (var i = 0; i < this.hotspots.length; ++i) {
- this.hotspots[i].layout ();
- }
-
- this.endRender (cause, data);
- }
- },
-
- /**
- * Render updated faces. Called as tiles are loaded from the server.
- *
- * @param [cause] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- * @param [data] parameter for the {@link bigshot.VRPanorama.RenderListener}s.
- */
- renderUpdated : function (cause, data) {
- if (!this.disposed && this.renderer.supportsUpdate ()) {
- this.beginRender (cause, data);
-
- var scene = this.renderer.createTexturedQuadScene ();
-
- for (var f in this.vrFaces) {
- if (this.vrFaces[f].isUpdated ()) {
- this.vrFaces[f].render (scene);
- }
- }
-
- scene.render ();
-
- for (var i = 0; i < this.hotspots.length; ++i) {
- this.hotspots[i].layout ();
- }
-
- this.endRender (cause, data);
- } else {
- this.render (cause, data);
- }
- },
-
- /**
- * The current drag mode.
- *
- * @private
- */
- dragMode : bigshot.VRPanorama.DRAG_GRAB,
-
- /**
- * Sets the mouse dragging mode.
- *
- * @param mode one of {@link bigshot.VRPanorama.DRAG_PAN} or {@link bigshot.VRPanorama.DRAG_GRAB}.
- */
- setDragMode : function (mode) {
- this.dragMode = mode;
- },
-
- addEventListeners : function () {
- for (var k in this.allListeners) {
- this.browser.registerListener (this.container, k, this.allListeners[k], false);
- }
- },
-
- removeEventListeners : function () {
- for (var k in this.allListeners) {
- this.browser.unregisterListener (this.container, k, this.allListeners[k], false);
- }
- },
-
- dragMouseDown : function (e) {
- this.dragStart = {
- clientX : e.clientX,
- clientY : e.clientY
- };
- this.dragLast = {
- clientX : e.clientX,
- clientY : e.clientY,
- dx : 0,
- dy : 0,
- dt : 1000000,
- time : new Date ().getTime ()
- };
- this.dragDistance = 0;
- },
-
- dragMouseUp : function (e) {
- // In case we got a mouse up with out a previous mouse down,
- // for example, double-click on title bar to maximize the
- // window
- if (this.dragStart == null || this.dragLast == null) {
- this.dragStart = null;
- this.dragLast = null;
- return;
- }
-
- this.dragStart = null;
- var dx = this.dragLast.dx;
- var dy = this.dragLast.dy;
- var ds = Math.sqrt (dx * dx + dy * dy);
- var dt = this.dragLast.dt;
- var dtb = new Date ().getTime () - this.dragLast.time;
- this.dragLast = null;
-
- var v = dt > 0 ? (ds / dt) : 0;
- if (v > 0.05 && dtb < 250 && dt > 20 && this.parameters.fling) {
- var scale = this.state.fov / this.renderer.getViewportHeight ();
-
- var t0 = new Date ().getTime ();
-
- var flingScale = this.parameters.flingScale;
-
- dx /= dt;
- dy /= dt;
-
- this.smoothRotate (function (dat) {
- var dt = new Date ().getTime () - t0;
- var fact = Math.pow (2, -dt * flingScale);
- var d = (dx * dat * scale) * fact;
- return fact > 0.01 ? d : null;
- }, function (dat) {
- var dt = new Date ().getTime () - t0;
- var fact = Math.pow (2, -dt * flingScale);
- var d = (dy * dat * scale) * fact;
- return fact > 0.01 ? d : null;
- }, function () {
- return null;
- });
- return true;
- } else {
- this.smoothRotate ();
- return false;
- }
- },
-
- dragMouseMove : function (e) {
- if (this.dragStart != null && this.currentGesture == null) {
- if (this.dragMode == bigshot.VRPanorama.DRAG_GRAB) {
- this.smoothRotate ();
- var scale = this.state.fov / this.renderer.getViewportHeight ();
- var dx = e.clientX - this.dragStart.clientX;
- var dy = e.clientY - this.dragStart.clientY;
- this.dragDistance += dx + dy;
- this.setYaw (this.getYaw () - dx * scale);
- this.setPitch (this.getPitch () - dy * scale);
- this.renderAsap ();
- this.dragStart = e;
- var dt = new Date ().getTime () - this.dragLast.time;
- if (dt > 20) {
- this.dragLast = {
- dx : this.dragLast.clientX - e.clientX,
- dy : this.dragLast.clientY - e.clientY,
- dt : dt,
- clientX : e.clientX,
- clientY : e.clientY,
- time : new Date ().getTime ()
- };
- }
- } else {
- var scale = 0.1 * this.state.fov / this.renderer.getViewportHeight ();
- var dx = e.clientX - this.dragStart.clientX;
- var dy = e.clientY - this.dragStart.clientY;
- this.dragDistance = dx + dy;
- this.smoothRotate (
- function () {
- return dx * scale;
- },
- function () {
- return dy * scale;
- });
- }
- }
- },
-
- onMouseDoubleClick : function (e, x, y) {
- var eventData = this.createVREventData ({
- type : "dblclick",
- clientX : e.clientX,
- clientY : e.clientY
- });
- this.fireEvent ("dblclick", eventData);
- if (!eventData.defaultPrevented) {
- this.smoothRotateToXY (x, y);
- }
- },
-
- mouseDoubleClick : function (e) {
- var pos = this.browser.getElementPosition (this.container);
- this.onMouseDoubleClick (e, e.clientX - pos.x, e.clientY - pos.y);
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureStart : function (event) {
- this.currentGesture = {
- startFov : this.getFov (),
- scale : event.scale
- };
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureEnd : function (event) {
- this.currentGesture = null;
- },
-
- /**
- * Begins a potential drag event.
- *
- * @private
- */
- gestureChange : function (event) {
- if (this.currentGesture) {
- var newFov = this.currentGesture.startFov / event.scale;
- this.setFov (newFov);
- this.renderAsap ();
- }
- },
-
- /**
- * Sets the maximum texture magnification.
- *
- * @param {number} v the maximum texture magnification
- * @see bigshot.VRPanoramaParameters#maxTextureMagnification
- */
- setMaxTextureMagnification : function (v) {
- this.maxTextureMagnification = v;
- },
-
- /**
- * Gets the current maximum texture magnification.
- *
- * @type number
- * @see bigshot.VRPanoramaParameters#maxTextureMagnification
- */
- getMaxTextureMagnification : function () {
- return this.maxTextureMagnification;
- },
-
- /**
- * Computes the minimum field of view where the resulting image will not
- * have to stretch the textures more than given by the
- * {@link bigshot.VRPanoramaParameters#maxTextureMagnification} parameter.
- *
- * @type number
- * @return the minimum FOV, below which it is necessary to stretch the
- * vr cube texture more than the given {@link bigshot.VRPanoramaParameters#maxTextureMagnification}
- */
- getMinFovFromViewportAndImage : function () {
- var halfHeight = this.renderer.getViewportHeight () / 2;
-
- var minFaceHeight = this.vrFaces[0].parameters.height;
- for (var i in this.vrFaces) {
- minFaceHeight = Math.min (minFaceHeight, this.vrFaces[i].parameters.height);
- }
-
- var edgeSizeY = this.maxTextureMagnification * minFaceHeight / 2;
-
- var wy = halfHeight / edgeSizeY;
-
- var mz = Math.atan (wy) * 180 / Math.PI;
-
- return mz * 2;
- },
-
- /**
- * Transforms screen coordinates to a world-coordinate ray.
- * @private
- */
- screenToRay : function (x, y) {
- var dray = this.screenToRayDelta (x, y);
- var ray = this.renderer.transformToWorld (dray);
- ray = Matrix.RotationY (-this.transformOffsets.y * Math.PI / 180.0).ensure4x4 ().xPoint3Dhom1 (ray);
- ray = Matrix.RotationX (-this.transformOffsets.p * Math.PI / 180.0).ensure4x4 ().xPoint3Dhom1 (ray);
- ray = Matrix.RotationZ (-this.transformOffsets.r * Math.PI / 180.0).ensure4x4 ().xPoint3Dhom1 (ray);
- return ray;
- },
-
- /**
- * @private
- */
- screenToRayDelta : function (x, y) {
- var halfHeight = this.renderer.getViewportHeight () / 2;
- var halfWidth = this.renderer.getViewportWidth () / 2;
- var x = (x - halfWidth);
- var y = (y - halfHeight);
-
- var edgeSizeY = Math.tan ((this.state.fov / 2) * Math.PI / 180);
- var edgeSizeX = edgeSizeY * this.renderer.getViewportWidth () / this.renderer.getViewportHeight ();
-
- var wx = x * edgeSizeX / halfWidth;
- var wy = y * edgeSizeY / halfHeight;
- var wz = -1.0;
-
- return {
- x : wx,
- y : wy,
- z : wz
- };
- },
-
- /**
- * Smoothly rotates the panorama so that the
- * point given by x and y, in pixels relative to the top left corner
- * of the panorama, ends up in the center of the viewport.
- *
- * @param {int} x the x-coordinate, in pixels from the left edge
- * @param {int} y the y-coordinate, in pixels from the top edge
- */
- smoothRotateToXY : function (x, y) {
- var polar = this.screenToPolar (x, y);
-
- this.smoothRotateTo (this.snapYaw (polar.yaw), this.snapPitch (polar.pitch), this.getFov (), this.state.fov / 200);
- },
-
- /**
- * Gives the step to take to slowly approach the
- * target value.
- *
- * @example
- * current = current + this.ease (current, target, 1.0);
- * @private
- */
- ease : function (current, target, speed, snapFrom) {
- var easingFrom = speed * 40;
- if (!snapFrom) {
- snapFrom = speed / 5;
- }
- var ignoreFrom = speed / 1000;
-
- var distance = current - target;
- if (distance > easingFrom) {
- distance = -speed;
- } else if (distance < -easingFrom) {
- distance = speed;
- } else if (Math.abs (distance) < snapFrom) {
- distance = -distance;
- } else if (Math.abs (distance) < ignoreFrom) {
- distance = 0;
- } else {
- distance = - (speed * distance) / (easingFrom);
- }
- return distance;
- },
-
- /**
- * Resets the "idle" clock.
- * @private
- */
- resetIdle : function () {
- this.idleCounter = 0;
- },
-
- /**
- * Idle clock.
- * @private
- */
- idleTick : function () {
- if (this.maxIdleCounter < 0) {
- return;
- }
- ++this.idleCounter;
- if (this.idleCounter == this.maxIdleCounter) {
- this.autoRotate ();
- }
- var that = this;
- setTimeout (function () {
- that.idleTick ();
- }, 1000);
- },
-
- /**
- * Sets the panorama to auto-rotate after a certain time has
- * elapsed with no user interaction. Default is disabled.
- *
- * @param {int} delay the delay in seconds. Set to < 0 to disable
- * auto-rotation when idle
- */
- autoRotateWhenIdle : function (delay) {
- this.maxIdleCounter = delay;
- this.idleCounter = 0;
- if (delay < 0) {
- return;
- } else if (this.maxIdleCounter > 0) {
- var that = this;
- setTimeout (function () {
- that.idleTick ();
- }, 1000);
- }
- },
-
- /**
- * Starts auto-rotation of the camera. If the yaw is constrained,
- * will pan back and forth between the yaw endpoints. Call
- * {@link #smoothRotate}() to stop the rotation.
- */
- autoRotate : function () {
- var that = this;
- var scale = this.state.fov / 400;
-
- var speed = scale;
- var dy = speed;
- this.smoothRotate (
- function () {
- var nextPos = that.getYaw () + dy;
- if (that.parameters.minYaw < that.parameters.maxYaw) {
- if (nextPos > that.parameters.maxYaw || nextPos < that.parameters.minYaw) {
- dy = -dy;
- }
- } else {
- // The only time when minYaw > maxYaw is when the interval
- // contains the 0 angle.
- if (nextPos > that.parameters.minYaw) {
- // ok, we're somewhere between minYaw and 0.0
- } else if (nextPos > that.parameters.maxYaw) {
- dy = -dy;
- } else {
- // ok, we're somewhere between 0.0 and maxYaw
- }
- }
- return dy;
- }, function () {
- return that.ease (that.getPitch (), 0.0, speed);
- }, function () {
- return that.ease (that.getFov (), 45.0, 0.1);
- });
- },
-
- /**
- * Smoothly rotates the panorama to the given state.
- *
- * @param {number} yaw the target yaw
- * @param {number} pitch the target pitch
- * @param {number} fov the target vertical field of view
- * @param {number} the speed to rotate with
- */
- smoothRotateTo : function (yaw, pitch, fov, speed) {
- var that = this;
- this.smoothRotate (
- function () {
- var distance = that.circleDistance (yaw, that.getYaw ());
- var d = -that.ease (0, distance, speed);
- return Math.abs (d) > 0.01 ? d : null;
- }, function () {
- var d = that.ease (that.getPitch (), pitch, speed);
- return Math.abs (d) > 0.01 ? d : null;
- }, function () {
- var d = that.ease (that.getFov (), fov, speed);
- return Math.abs (d) > 0.01 ? d : null;
- }
- );
- },
-
-
- /**
- * Smoothly rotates the camera. If all of the dp, dy and df functions are null, stops
- * any smooth rotation.
- *
- * @param {function()} [dy] function giving the yaw increment for the next frame
- * or null if no further yaw movement is required
- * @param {function()} [dp] function giving the pitch increment for the next frame
- * or null if no further pitch movement is required
- * @param {function()} [df] function giving the field of view (degrees) increment
- * for the next frame or null if no further fov adjustment is required
- */
- smoothRotate : function (dy, dp, df) {
- ++this.smoothrotatePermit;
- var savedPermit = this.smoothrotatePermit;
- if (!dp && !dy && !df) {
- return;
- }
-
- var that = this;
- var fs = {
- dy : dy,
- dp : dp,
- df : df,
- t : new Date ().getTime ()
- };
- var stepper = function () {
- if (that.smoothrotatePermit == savedPermit) {
- var now = new Date ().getTime ();
- var dat = now - fs.t;
- fs.t = now;
-
- var anyFunc = false;
- if (fs.dy) {
- var d = fs.dy(dat);
- if (d != null) {
- anyFunc = true;
- that.setYaw (that.getYaw () + d);
- } else {
- fs.dy = null;
- }
- }
-
- if (fs.dp) {
- var d = fs.dp(dat);
- if (d != null) {
- anyFunc = true;
- that.setPitch (that.getPitch () + d);
- } else {
- fs.dp = null;
- }
- }
-
- if (fs.df) {
- var d = fs.df(dat);
- if (d != null) {
- anyFunc = true;
- that.setFov (that.getFov () + d);
- } else {
- fs.df = null;
- }
- }
- that.render ();
- if (anyFunc) {
- that.browser.requestAnimationFrame (stepper, that.renderer.getElement ());
- }
- }
- };
- stepper ();
- },
-
- /**
- * Translates mouse wheel events.
- * @private
- */
- mouseWheel : function (event){
- var delta = 0;
- if (!event) /* For IE. */
- event = window.event;
- if (event.wheelDelta) { /* IE/Opera. */
- delta = event.wheelDelta / 120;
- /*
- * In Opera 9, delta differs in sign as compared to IE.
- */
- if (window.opera)
- delta = -delta;
- } else if (event.detail) { /* Mozilla case. */
- /*
- * In Mozilla, sign of delta is different than in IE.
- * Also, delta is multiple of 3.
- */
- delta = -event.detail;
- }
-
- /*
- * If delta is nonzero, handle it.
- * Basically, delta is now positive if wheel was scrolled up,
- * and negative, if wheel was scrolled down.
- */
- if (delta) {
- this.mouseWheelHandler (delta);
- }
-
- /*
- * Prevent default actions caused by mouse wheel.
- * That might be ugly, but we handle scrolls somehow
- * anyway, so don't bother here..
- */
- if (event.preventDefault) {
- event.preventDefault ();
- }
- event.returnValue = false;
- },
-
- /**
- * Utility function to interpret mouse wheel events.
- * @private
- */
- mouseWheelHandler : function (delta) {
- var that = this;
- var target = null;
- if (delta > 0) {
- if (this.getFov () > this.parameters.minFov) {
- target = this.getFov () * 0.9;
- }
- }
- if (delta < 0) {
- if (this.getFov () < this.parameters.maxFov) {
- target = this.getFov () / 0.9;
- }
- }
- if (target != null) {
- this.smoothRotate (null, null, function () {
- var df = (target - that.getFov ()) / 1.5;
- return Math.abs (df) > 0.01 ? df : null;
- });
- }
- },
-
- /**
- * Maximizes the image to cover the browser viewport.
- * The container div is removed from its parent node upon entering
- * full screen mode. When leaving full screen mode, the container
- * is appended to its old parent node. To avoid rearranging the
- * nodes, wrap the container in an extra div.
- *
- * <p>For unknown reasons (probably security), browsers will
- * not let you open a window that covers the entire screen.
- * Even when specifying "fullscreen=yes", all you get is a window
- * that has a title bar and only covers the desktop (not any task
- * bars or the like). For now, this is the best that I can do,
- * but should the situation change I'll update this to be
- * full-screen<i>-ier</i>.
- *
- * @param {function()} [onClose] function that is called when the user
- * exits full-screen mode
- * @public
- */
- fullScreen : function (onClose) {
- if (this.fullScreenHandler) {
- return;
- }
-
- var message = document.createElement ("div");
- message.style.position = "absolute";
- message.style.fontSize = "16pt";
- message.style.top = "128px";
- message.style.width = "100%";
- message.style.color = "white";
- message.style.padding = "16px";
- message.style.zIndex = "9999";
- message.style.textAlign = "center";
- message.style.opacity = "0.75";
- message.innerHTML = "<span style='border-radius: 16px; -moz-border-radius: 16px; padding: 16px; padding-left: 32px; padding-right: 32px; background:black'>Press Esc to exit full screen mode.</span>";
-
- var that = this;
-
- this.fullScreenHandler = new bigshot.FullScreen (this.container);
- this.fullScreenHandler.restoreSize = this.sizeContainer == null;
-
- this.fullScreenHandler.addOnResize (function () {
- that.onresize ();
- });
-
- this.fullScreenHandler.addOnClose (function () {
- if (message.parentNode) {
- try {
- div.removeChild (message);
- } catch (x) {
- }
- }
- that.fullScreenHandler = null;
- });
-
- if (onClose) {
- this.fullScreenHandler.addOnClose (function () {
- onClose ();
- });
- }
-
- this.removeEventListeners ();
- this.fullScreenHandler.open ();
- this.addEventListeners ();
- // Safari compatibility - must update after entering fullscreen.
- // 1s should be enough so we enter FS, but not enough for the
- // user to wonder if something is wrong.
- var r = function () {
- that.render ();
- };
- setTimeout (r, 1000);
- setTimeout (r, 2000);
- setTimeout (r, 3000);
-
- if (this.fullScreenHandler.getRootElement ()) {
- this.fullScreenHandler.getRootElement ().appendChild (message);
-
- setTimeout (function () {
- var opacity = 0.75;
- var iter = function () {
- opacity -= 0.02;
- if (message.parentNode) {
- if (opacity <= 0) {
- message.style.display = "none";
- try {
- div.removeChild (message);
- } catch (x) {}
- } else {
- message.style.opacity = opacity;
- setTimeout (iter, 20);
- }
- }
- };
- setTimeout (iter, 20);
- }, 3500);
- }
-
- return function () {
- that.removeEventListeners ();
- that.fullScreenHandler.close ();
- that.addEventListeners ();
- };
- },
-
- /**
- * Right-sizes the canvas container.
- * @private
- */
- onresize : function () {
- if (this.fullScreenHandler == null || !this.fullScreenHandler.isFullScreen) {
- if (this.sizeContainer) {
- var s = this.browser.getElementSize (this.sizeContainer);
- this.renderer.resize (s.w, s.h);
- }
- } else {
- this.container.style.width = window.innerWidth + "px";
- this.container.style.height = window.innerHeight + "px";
- var s = this.browser.getElementSize (this.container);
- this.renderer.resize (s.w, s.h);
- }
- this.renderer.onresize ();
- this.renderAsap ();
- },
-
- /**
- * Posts a render() call via a timeout or the requestAnimationFrame API.
- * Use when the render call must be done as soon as possible, but
- * can't be done in the current call context.
- */
- renderAsap : function () {
- if (!this.renderAsapPermitTaken && !this.disposed) {
- this.renderAsapPermitTaken = true;
- var that = this;
- this.browser.requestAnimationFrame (function () {
- that.renderAsapPermitTaken = false;
- that.render ();
- }, this.renderer.getElement ());
- }
- },
-
-
- /**
- * Automatically resizes the canvas element to the size of the
- * given element on resize.
- *
- * @param {HTMLElement} sizeContainer the element to use. Set to <code>null</code>
- * to disable.
- */
- autoResizeContainer : function (sizeContainer) {
- this.sizeContainer = sizeContainer;
- }
-}
-
-/**
- * Fired when the user double-clicks on the panorama.
- *
- * @name bigshot.VRPanorama#dblclick
- * @event
- * @param {bigshot.VREvent} event the event object
- */
-
-bigshot.Object.extend (bigshot.VRPanorama, bigshot.EventDispatcher);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Abstract base class for panorama hotspots.
- *
- * @class Abstract base class for panorama hotspots.
- *
- * A Hotspot is simply an HTML element that is moved / hidden etc.
- * to overlay a given position in the panorama.
- *
- * @param {bigshot.VRPanorama} panorama the panorama to attach this hotspot to
- */
-bigshot.VRHotspot = function (panorama) {
- this.panorama = panorama;
-
- /**
- * The method to use for dealing with hotspots that extend outside the
- * viewport. Note that {@link #CLIP_ADJUST} et al are functions, not constants.
- * To set the value, you must call the function to get a clipping strategy:
- *
- * @example
- * var hotspot = ...;
- * // note the function call below ---------------v
- * hotspot.clippingStrategy = hotspot.CLIP_ADJUST ();
- *
- * @see bigshot.VRHotspot#CLIP_ADJUST
- * @see bigshot.VRHotspot#CLIP_CENTER
- * @see bigshot.VRHotspot#CLIP_FRACTION
- * @see bigshot.VRHotspot#CLIP_ZOOM
- * @see bigshot.VRHotspot#CLIP_FADE
- * @see bigshot.VRHotspot#clip
- * @type function(clipData)
- * @default bigshot.VRHotspot#CLIP_ADJUST
- */
- this.clippingStrategy = bigshot.VRHotspot.CLIP_ADJUST (panorama);
-
-}
-
-/**
- * Hides the hotspot if less than <code>frac</code> of its area is visible.
- *
- * @param {number} frac the fraction (0.0 - 1.0) of the hotspot that must be visible for
- * it to be shown.
- * @type function(clipData)
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_FRACTION = function (panorama, frac) {
- return function (clipData) {
- var r = {
- x0 : Math.max (clipData.x, 0),
- y0 : Math.max (clipData.y, 0),
- x1 : Math.min (clipData.x + clipData.w, panorama.renderer.getViewportWidth ()),
- y1 : Math.min (clipData.y + clipData.h, panorama.renderer.getViewportHeight ())
- };
- var full = clipData.w * clipData.h;
- var visibleWidth = (r.x1 - r.x0);
- var visibleHeight = (r.y1 - r.y0);
- if (visibleWidth > 0 && visibleHeight > 0) {
- var visible = visibleWidth * visibleHeight;
-
- return (visible / full) >= frac;
- } else {
- return false;
- }
- }
-};
-
-/**
- * Hides the hotspot if its center is outside the viewport.
- *
- * @type function(clipData)
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_CENTER = function (panorama) {
- return function (clipData) {
- var c = {
- x : clipData.x + clipData.w / 2,
- y : clipData.y + clipData.h / 2
- };
- return c.x >= 0 && c.x < panorama.renderer.getViewportWidth () &&
- c.y >= 0 && c.y < panorama.renderer.getViewportHeight ();
- }
-}
-
-/**
- * Resizes the hotspot to fit in the viewport. Hides the hotspot if
- * it is completely outside the viewport.
- *
- * @type function(clipData)
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_ADJUST = function (panorama) {
- return function (clipData) {
- if (clipData.x < 0) {
- clipData.w -= -clipData.x;
- clipData.x = 0;
- }
- if (clipData.y < 0) {
- clipData.h -= -clipData.y;
- clipData.y = 0;
- }
- if (clipData.x + clipData.w > panorama.renderer.getViewportWidth ()) {
- clipData.w = panorama.renderer.getViewportWidth () - clipData.x - 1;
- }
- if (clipData.y + clipData.h > panorama.renderer.getViewportHeight ()) {
- clipData.h = panorama.renderer.getViewportHeight () - clipData.y - 1;
- }
-
- return clipData.w > 0 && clipData.h > 0;
- }
-}
-
-/**
- * Shrinks the hotspot as it approaches the viewport edges.
- *
- * @param s The full size of the hotspot.
- * @param s.w The full width of the hotspot, in pixels.
- * @param s.h The full height of the hotspot, in pixels.
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_ZOOM = function (panorama, s, maxDistanceInViewportHeights) {
- return function (clipData) {
- if (clipData.x >= 0 && clipData.y >= 0 && (clipData.x + s.w) < panorama.renderer.getViewportWidth ()
- && (clipData.y + s.h) < panorama.renderer.getViewportHeight ()) {
- clipData.w = s.w;
- clipData.h = s.h;
- return true;
- }
-
- var distance = 0;
- if (clipData.x < 0) {
- distance = Math.max (-clipData.x, distance);
- }
- if (clipData.y < 0) {
- distance = Math.max (-clipData.y, distance);
- }
- if (clipData.x + s.w > panorama.renderer.getViewportWidth ()) {
- distance = Math.max (clipData.x + s.w - panorama.renderer.getViewportWidth (), distance);
- }
- if (clipData.y + s.h > panorama.renderer.getViewportHeight ()) {
- distance = Math.max (clipData.y + s.h - panorama.renderer.getViewportHeight (), distance);
- }
-
- distance /= panorama.renderer.getViewportHeight ();
- if (distance > maxDistanceInViewportHeights) {
- return false;
- }
-
- var scale = 1 / (1 + distance);
-
- clipData.w = s.w * scale;
- clipData.h = s.w * scale;
- if (clipData.x < 0) {
- clipData.x = 0;
- }
- if (clipData.y < 0) {
- clipData.y = 0;
- }
- if (clipData.x + clipData.w > panorama.renderer.getViewportWidth ()) {
- clipData.x = panorama.renderer.getViewportWidth () - clipData.w;
- }
- if (clipData.y + clipData.h > panorama.renderer.getViewportHeight ()) {
- clipData.y = panorama.renderer.getViewportHeight () - clipData.h;
- }
-
- return true;
- }
-}
-
-/**
- * Progressively fades the hotspot as it gets closer to the viewport edges.
- *
- * @param {number} borderSizeInPixels the distance from the edge, in pixels,
- * where the hotspot is completely opaque.
- * @see bigshot.VRHotspot#clip
- * @see bigshot.VRHotspot#clippingStrategy
- */
-bigshot.VRHotspot.CLIP_FADE = function (panorama, borderSizeInPixels) {
- return function (clipData) {
- var distance = Math.min (
- clipData.x,
- clipData.y,
- panorama.renderer.getViewportWidth () - (clipData.x + clipData.w),
- panorama.renderer.getViewportHeight () - (clipData.y + clipData.h));
-
- if (distance <= 0) {
- return false;
- } else if (distance <= borderSizeInPixels) {
- clipData.opacity = (distance / borderSizeInPixels);
- return true;
- } else {
- clipData.opacity = 1.0;
- return true;
- }
- }
-}
-
-bigshot.VRHotspot.prototype = {
-
- /**
- * Layout and resize the hotspot. Called by the panorama.
- */
- layout : function () {},
-
- /**
- * Helper function to rotate a point around an axis.
- *
- * @param {number} ang the angle
- * @param {bigshot.Point3D} vector the vector to rotate around
- * @param {Vector} point the point
- * @type Vector
- * @private
- */
- rotate : function (ang, vector, point) {
- var arad = ang * Math.PI / 180.0;
- var m = Matrix.Rotation(arad, $V([vector.x, vector.y, vector.z])).ensure4x4 ();
- return m.xPoint3Dhom1 (point);
- },
-
- /**
- * Converts the polar coordinates to world coordinates.
- * The distance is assumed to be 1.0.
- *
- * @param yaw the yaw, in degrees
- * @param pitch the pitch, in degrees
- * @type bigshot.Point3D
- */
- toVector : function (yaw, pitch) {
- var point = { x : 0, y : 0, z : -1 };
- point = this.rotate (-pitch, { x : 1, y : 0, z : 0 }, point);
- point = this.rotate (-yaw, { x : 0, y : 1, z : 0 }, point);
- return point;
- },
-
- /**
- * Converts the world-coordinate point p to screen coordinates.
- *
- * @param {bigshot.Point3D} p the world-coordinate point
- * @type point
- */
- toScreen : function (p) {
- var res = this.panorama.renderer.transformToScreen (p)
- return res;
- },
-
- /**
- * Clips the hotspot against the viewport. Both parameters
- * are in/out. Clipping is done by adjusting the values of the
- * parameters.
- *
- * @param clipData Information about the hotspot.
- * @param {number} clipData.x the x-coordinate of the top-left corner of the hotspot, in pixels.
- * @param {number} clipData.y the y-coordinate of the top-left corner of the hotspot, in pixels.
- * @param {number} clipData.w the width of the hotspot, in pixels.
- * @param {number} clipData.h the height of the hotspot, in pixels.
- * @param {number} [clipData.opacity] the opacity of the hotspot, ranging from 0.0 (transparent)
- * to 1.0 (opaque). If set, the opacity of the hotspot element is adjusted.
- * @type boolean
- * @return true if the hotspot is visible, false otherwise
- */
- clip : function (clipData) {
- return this.clippingStrategy (clipData);
- }
-}
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new point-hotspot and attaches it to a VR panorama.
- *
- * @class A VR panorama point-hotspot.
- *
- * A Hotspot is simply an HTML element that is moved / hidden etc.
- * to overlay a given position in the panorama. The element is moved
- * by setting its <code>style.top</code> and <code>style.left</code>
- * values.
- *
- * @augments bigshot.VRHotspot
- * @param {bigshot.VRPanorama} panorama the panorama to attach this hotspot to
- * @param {number} yaw the yaw coordinate of the hotspot
- * @param {number} pitch the pitch coordinate of the hotspot
- * @param {HTMLElement} element the HTML element
- * @param {number} offsetX the offset to add to the screen coordinate corresponding
- * to the hotspot's polar coordinates. Use this to center the hotspot horizontally.
- * @param {number} offsetY the offset to add to the screen coordinate corresponding
- * to the hotspot's polar coordinates. Use this to center the hotspot vertically.
- */
-bigshot.VRPointHotspot = function (panorama, yaw, pitch, element, offsetX, offsetY) {
- bigshot.VRHotspot.call (this, panorama);
- this.element = element;
- this.offsetX = offsetX;
- this.offsetY = offsetY;
- this.point = this.toVector (yaw, pitch);
-}
-
-bigshot.VRPointHotspot.prototype = {
- layout : function () {
- var p = this.toScreen (this.point);
-
- var visible = false;
- if (p != null) {
- var s = this.panorama.browser.getElementSize (this.element);
- p.w = s.w;
- p.h = s.h;
-
- p.x += this.offsetX;
- p.y += this.offsetY;
-
- if (this.clip (p)) {
- this.element.style.top = (p.y) + "px";
- this.element.style.left = (p.x) + "px";
- this.element.style.width = (p.w) + "px";
- this.element.style.height = (p.h) + "px";
- if (p.opacity) {
- this.element.style.opacity = p.opacity;
- }
- this.element.style.visibility = "inherit";
- visible = true;
- }
- }
-
- if (!visible) {
- this.element.style.visibility = "hidden";
- }
- }
-}
-
-bigshot.Object.extend (bigshot.VRPointHotspot, bigshot.VRHotspot);
-bigshot.Object.validate ("bigshot.VRPointHotspot", bigshot.VRHotspot);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new rectangular hotspot and attaches it to a VR panorama.
- *
- * @class A rectangular VR panorama hotspot.
- *
- * A rectangular hotspot is simply an HTML element that is moved / resized / hidden etc.
- * to overlay a given rectangle in the panorama. The element is moved
- * by setting its <code>style.top</code> and <code>style.left</code>
- * values, and resized by setting its <code>style.width</code> and <code>style.height</code>
- * values.
- *
- * @augments bigshot.VRHotspot
- * @param {bigshot.VRPanorama} panorama the panorama to attach this hotspot to
- * @param {number} yaw0 the yaw coordinate of the top-left corner of the hotspot
- * @param {number} pitch0 the pitch coordinate of the top-left corner of the hotspot
- * @param {number} yaw1 the yaw coordinate of the bottom-right corner of the hotspot
- * @param {number} pitch1 the pitch coordinate of the bottom-right corner of the hotspot
- * @param {HTMLElement} element the HTML element
- */
-bigshot.VRRectangleHotspot = function (panorama, yaw0, pitch0, yaw1, pitch1, element) {
- bigshot.VRHotspot.call (this, panorama);
-
- this.element = element;
- this.point0 = this.toVector (yaw0, pitch0);
- this.point1 = this.toVector (yaw1, pitch1);
-}
-
-bigshot.VRRectangleHotspot.prototype = {
- layout : function () {
- var p = this.toScreen (this.point0);
- var p1 = this.toScreen (this.point1);
-
- var visible = false;
- if (p != null && p1 != null) {
- var cd = {
- x : p.x,
- y : p.y,
- opacity : 1.0,
- w : p1.x - p.x,
- h : p1.y - p.y
- };
-
- if (this.clip (cd)) {
- this.element.style.top = (cd.y) + "px";
- this.element.style.left = (cd.x) + "px";
- this.element.style.width = (cd.w) + "px";
- this.element.style.height = (cd.h) + "px";
- this.element.style.visibility = "inherit";
- visible = true;
- }
- }
-
- if (!visible) {
- this.element.style.visibility = "hidden";
- }
- }
-}
-
-bigshot.Object.extend (bigshot.VRRectangleHotspot, bigshot.VRHotspot);
-bigshot.Object.validate ("bigshot.VRRectangleHotspot", bigshot.VRHotspot);
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new parameter block.
- *
- * @class Parameters for the adaptive LOD monitor.
- */
-bigshot.AdaptiveLODMonitorParameters = function (values) {
-
- /**
- * The VR panorama to adjust.
- *
- * @type bigshot.VRPanorama
- */
- this.vrPanorama = null;
-
- /**
- * The target framerate in frames per second.
- * The monitor will try to achieve an average frame render time
- * of <i>1 / targetFps</i> seconds.
- *
- * @default 30
- * @type float
- */
- this.targetFps = 30;
-
- /**
- * The tolerance for the rendering time. The monitor will adjust the
- * level of detail if the average frame render time rises above
- * <i>target frame render time * (1.0 + tolerance)</i> or falls below
- * <i>target frame render time / (1.0 + tolerance)</i>.
- *
- * @default 0.3
- * @type float
- */
- this.tolerance = 0.3;
-
- /**
- * The rate at which the level of detail is adjusted.
- * For detail increase, the detail is multiplied with (1.0 + rate),
- * for decrease divided.
- *
- * @default 0.1
- * @type float
- */
- this.rate = 0.1;
-
- /**
- * Minimum texture magnification.
- *
- * @default 1.5
- * @type float
- */
- this.minMag = 1.5;
-
- /**
- * Maximum texture magnification.
- *
- * @default 16
- * @type float
- */
- this.maxMag = 16;
-
- /**
- * Texture magnification for HQ render passes.
- *
- * @default 1.5
- * @type float
- */
- this.hqRenderMag = 1.5;
-
- /**
- * Delay in milliseconds before executing
- * a HQ render pass.
- *
- * @default 2000
- * @type int
- */
- this.hqRenderDelay = 2000;
-
- /**
- * Interval in milliseconds for the
- * HQ render pass timer.
- *
- * @default 1000
- * @type int
- */
- this.hqRenderInterval = 1000;
-
- if (values) {
- for (var k in values) {
- this[k] = values[k];
- }
- }
-
- this.merge = function (values, overwrite) {
- for (var k in values) {
- if (overwrite || !this[k]) {
- this[k] = values[k];
- }
- }
- }
- return this;
-};
-/*
- * Copyright 2010 - 2012 Leo Sutic <leo.sutic@gmail.com>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/**
- * Creates a new adaptive level-of-detail monitor.
- *
- * @class An adaptive LOD monitor that adjusts the level of detail of a VR panorama
- * to achieve a desired frame rate. To connect it to a VR panorama, use the
- * {@link bigshot.AdaptiveLODMonitor#getListener} method to get a render listener
- * that can be passed to {@link bigshot.VRPanorama#addRenderListener}.
- *
- * <p>The monitor maintains two render modes - a high quality one with a fixed
- * level of detail, and a low(er) quality one with variable level of detail.
- * If the panorama is idle for more than a set interval, a high-quality render is
- * performed.
- *
- * @param {bigshot.AdaptiveLODMonitorParameters} parameters parameters for the LOD monitor.
- *
- * @see bigshot.AdaptiveLODMonitorParameters for a list of parameters
- *
- * @example
- * var bvr = new bigshot.VRPanorama ( ... );
- * var lodMonitor = new bigshot.AdaptiveLODMonitor (
- * new bigshot.AdaptiveLODMonitorParameters ({
- * vrPanorama : bvr,
- * targetFps : 30,
- * tolerance : 0.3,
- * rate : 0.1,
- * minMag : 1.5,
- * maxMag : 16
- * }));
- * bvr.addRenderListener (lodMonitor.getListener ());
- */
-bigshot.AdaptiveLODMonitor = function (parameters) {
- this.setParameters (parameters);
-
- /**
- * The current adaptive detail level.
- * @type float
- * @private
- */
- this.currentAdaptiveMagnification = parameters.vrPanorama.getMaxTextureMagnification ();
-
- /**
- * The number of frames that have been rendered.
- * @type int
- * @private
- */
- this.frames = 0;
-
- /**
- * The total number of times we have sampled the render time.
- * @type int
- * @private
- */
- this.samples = 0;
-
- /**
- * The sum of sample times from all samples of render time in milliseconds.
- * @type int
- * @private
- */
- this.renderTimeTotal = 0;
-
- /**
- * The sum of sample times from the recent sample pass in milliseconds.
- * @type int
- * @private
- */
- this.renderTimeLast = 0;
-
- /**
- * The number of samples currently done in the recent sample pass.
- * @type int
- * @private
- */
- this.samplesLast = 0;
-
- /**
- * The start time, in milliseconds, of the last sample.
- * @type int
- * @private
- */
- this.startTime = 0;
-
- /**
- * The time, in milliseconds, when the panorama was last rendered.
- * @type int
- * @private
- */
- this.lastRender = 0;
-
- this.hqRender = false;
- this.hqMode = false;
- this.hqRenderWaiting = false;
-
- /**
- * Flag to enable / disable the monitor.
- * @type boolean
- * @private
- */
- this.enabled = true;
-
- var that = this;
- this.listenerFunction = function (state, cause, data) {
- that.listener (state, cause, data);
- };
-};
-
-bigshot.AdaptiveLODMonitor.prototype = {
- averageRenderTime : function () {
- if (this.samples > 0) {
- return this.renderTimeTotal / this.samples;
- } else {
- return -1;
- }
- },
-
- /**
- * @param {bigshot.AdaptiveLODMonitorParameters} parameters
- */
- setParameters : function (parameters) {
- this.parameters = parameters;
- this.targetTime = 1000 / this.parameters.targetFps;
-
- this.lowerTime = this.targetTime / (1.0 + this.parameters.tolerance);
- this.upperTime = this.targetTime * (1.0 + this.parameters.tolerance);
- },
-
- setEnabled : function (enabled) {
- this.enabled = enabled;
- },
-
- averageRenderTimeLast : function () {
- if (this.samples > 0) {
- return this.renderTimeLast / this.samplesLast;
- } else {
- return -1;
- }
- },
-
- getListener : function () {
- return this.listenerFunction;
- },
-
- increaseDetail : function () {
- this.currentAdaptiveMagnification = Math.max (this.parameters.minMag, this.currentAdaptiveMagnification / (1.0 + this.parameters.rate));
- },
-
- decreaseDetail : function () {
- this.currentAdaptiveMagnification = Math.min (this.parameters.maxMag, this.currentAdaptiveMagnification * (1.0 + this.parameters.rate));
- },
-
- sample : function () {
- var deltat = new Date ().getTime () - this.startTime;
- this.samples++;
- this.renderTimeTotal += deltat;
-
- this.samplesLast++;
- this.renderTimeLast += deltat;
-
- if (this.samplesLast > 4) {
- var averageLast = this.renderTimeLast / this.samplesLast;
-
- if (averageLast < this.lowerTime) {
- this.increaseDetail ();
- } else if (averageLast > this.upperTime) {
- this.decreaseDetail ();
- }
-
- this.samplesLast = 0;
- this.renderTimeLast = 0;
- }
- },
-
- hqRenderTick : function () {
- if (this.lastRender < new Date ().getTime () - this.parameters.hqRenderDelay) {
- this.hqRender = true;
- this.hqMode = true;
- if (this.enabled) {
- this.parameters.vrPanorama.setMaxTextureMagnification (this.parameters.hqRenderMag);
- this.parameters.vrPanorama.render ();
- }
-
- this.hqRender = false;
- this.hqRenderWaiting = false;
- } else {
- var that = this;
- setTimeout (function () {
- that.hqRenderTick ();
- }, this.parameters.hqRenderInterval);
- }
- },
-
- listener : function (state, cause, data) {
- if (!this.enabled) {
- return;
- }
-
- if (this.hqRender) {
- return;
- }
-
- if (this.hqMode && cause == bigshot.VRPanorama.ONRENDER_TEXTURE_UPDATE) {
- this.parameters.vrPanorama.setMaxTextureMagnification (this.parameters.minMag);
- return;
- } else {
- this.hqMode = false;
- }
-
- this.parameters.vrPanorama.setMaxTextureMagnification (this.currentAdaptiveMagnification);
-
- this.frames++;
- if ((this.frames < 20 || this.frames % 5 == 0) && state == bigshot.VRPanorama.ONRENDER_BEGIN) {
- this.startTime = new Date ().getTime ();
- this.lastRender = this.startTime;
- var that = this;
- setTimeout (function () {
- that.sample ();
- }, 1);
- if (!this.hqRenderWaiting) {
- this.hqRenderWaiting = true;
- setTimeout (function () {
- that.hqRenderTick ();
- }, this.parameters.hqRenderInterval);
- }
- }
- }
-};
-}
diff --git a/js/vendor/dompurify/purify.js b/js/vendor/dompurify/purify.js
new file mode 100644
index 00000000..552eaafe
--- /dev/null
+++ b/js/vendor/dompurify/purify.js
@@ -0,0 +1,694 @@
+;(function(factory) {
+ 'use strict';
+ /* global window: false, define: false, module: false */
+ var root = typeof window === 'undefined' ? null : window;
+
+ if (typeof define === 'function' && define.amd) {
+ define(function(){ return factory(root); });
+ } else if (typeof module !== 'undefined') {
+ module.exports = factory(root);
+ } else {
+ root.DOMPurify = factory(root);
+ }
+}(function factory(window) {
+ 'use strict';
+
+ var DOMPurify = function(window) {
+ return factory(window);
+ };
+
+ /**
+ * Version label, exposed for easier checks
+ * if DOMPurify is up to date or not
+ */
+ DOMPurify.version = '0.6.5';
+
+ if (!window || !window.document || window.document.nodeType !== 9) {
+ // not running in a browser, provide a factory function
+ // so that you can pass your own Window
+ DOMPurify.isSupported = false;
+ return DOMPurify;
+ }
+
+ var document = window.document;
+ var originalDocument = document;
+ var DocumentFragment = window.DocumentFragment;
+ var HTMLTemplateElement = window.HTMLTemplateElement;
+ var NodeFilter = window.NodeFilter;
+ var NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap;
+ var Text = window.Text;
+ var Comment = window.Comment;
+
+ // As per issue #47, the web-components registry is inherited by a
+ // new document created via createHTMLDocument. As per the spec
+ // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)
+ // a new empty registry is used when creating a template contents owner
+ // document, so we use that as our parent document to ensure nothing
+ // is inherited.
+ if (typeof HTMLTemplateElement === 'function') {
+ document = document.createElement('template').content.ownerDocument;
+ }
+ var implementation = document.implementation;
+ var createNodeIterator = document.createNodeIterator;
+ var getElementsByTagName = document.getElementsByTagName;
+ var createDocumentFragment = document.createDocumentFragment;
+ var importNode = originalDocument.importNode;
+
+ var hooks = {};
+
+ /**
+ * Expose whether this browser supports running the full DOMPurify.
+ */
+ DOMPurify.isSupported =
+ typeof implementation.createHTMLDocument !== 'undefined' &&
+ document.documentMode !== 9;
+
+ /* Add properties to a lookup table */
+ var _addToSet = function(set, array) {
+ var l = array.length;
+ while (l--) {
+ set[array[l]] = true;
+ }
+ return set;
+ };
+
+ /* Shallow clone an object */
+ var _cloneObj = function(object) {
+ var newObject = {};
+ var property;
+ for (property in object) {
+ if (object.hasOwnProperty(property)) {
+ newObject[property] = object[property];
+ }
+ }
+ return newObject;
+ };
+
+ /**
+ * We consider the elements and attributes below to be safe. Ideally
+ * don't add any new ones but feel free to remove unwanted ones.
+ */
+
+ /* allowed element names */
+ var ALLOWED_TAGS = null;
+ var DEFAULT_ALLOWED_TAGS = _addToSet({}, [
+
+ // HTML
+ 'a','abbr','acronym','address','area','article','aside','audio','b',
+ 'bdi','bdo','big','blink','blockquote','body','br','button','canvas',
+ 'caption','center','cite','code','col','colgroup','content','data',
+ 'datalist','dd','decorator','del','details','dfn','dir','div','dl','dt',
+ 'element','em','fieldset','figcaption','figure','font','footer','form',
+ 'h1','h2','h3','h4','h5','h6','head','header','hgroup','hr','html','i',
+ 'img','input','ins','kbd','label','legend','li','main','map','mark',
+ 'marquee','menu','menuitem','meter','nav','nobr','ol','optgroup',
+ 'option','output','p','pre','progress','q','rp','rt','ruby','s','samp',
+ 'section','select','shadow','small','source','spacer','span','strike',
+ 'strong','style','sub','summary','sup','table','tbody','td','template',
+ 'textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var',
+ 'video','wbr',
+
+ // SVG
+ 'svg','altglyph','altglyphdef','altglyphitem','animatecolor',
+ 'animatemotion','animatetransform','circle','clippath','defs','desc',
+ 'ellipse','font','g','glyph','glyphref','hkern','image','line',
+ 'lineargradient','marker','mask','metadata','mpath','path','pattern',
+ 'polygon','polyline','radialgradient','rect','stop','switch','symbol',
+ 'text','textpath','title','tref','tspan','view','vkern',
+
+ //MathML
+ 'math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr',
+ 'mmuliscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow',
+ 'ms','mpspace','msqrt','mystyle','msub','msup','msubsup','mtable','mtd',
+ 'mtext','mtr','munder','munderover',
+
+ //Text
+ '#text'
+ ]);
+
+ /* Allowed attribute names */
+ var ALLOWED_ATTR = null;
+ var DEFAULT_ALLOWED_ATTR = _addToSet({}, [
+
+ // HTML
+ 'accept','action','align','alt','autocomplete','background','bgcolor',
+ 'border','cellpadding','cellspacing','checked','cite','class','clear','color',
+ 'cols','colspan','coords','datetime','default','dir','disabled',
+ 'download','enctype','face','for','headers','height','hidden','high','href',
+ 'hreflang','id','ismap','label','lang','list','loop', 'low','max',
+ 'maxlength','media','method','min','multiple','name','noshade','novalidate',
+ 'nowrap','open','optimum','pattern','placeholder','poster','preload','pubdate',
+ 'radiogroup','readonly','rel','required','rev','reversed','rows',
+ 'rowspan','spellcheck','scope','selected','shape','size','span',
+ 'srclang','start','src','step','style','summary','tabindex','title',
+ 'type','usemap','valign','value','width','xmlns',
+
+ // SVG
+ 'accent-height','accumulate','additivive','alignment-baseline',
+ 'ascent','azimuth','baseline-shift','bias','clip','clip-path',
+ 'clip-rule','color','color-interpolation','color-interpolation-filters',
+ 'color-profile','color-rendering','cx','cy','d','dy','dy','direction',
+ 'display','divisor','dur','elevation','end','fill','fill-opacity',
+ 'fill-rule','filter','flood-color','flood-opacity','font-family',
+ 'font-size','font-size-adjust','font-stretch','font-style','font-variant',
+ 'font-weight','image-rendering','in','in2','k1','k2','k3','k4','kerning',
+ 'letter-spacing','lighting-color','local','marker-end','marker-mid',
+ 'marker-start','max','mask','mode','min','offset','operator','opacity',
+ 'order','overflow','paint-order','path','points','r','rx','ry','radius',
+ 'restart','scale','seed','shape-rendering','stop-color','stop-opacity',
+ 'stroke-dasharray','stroke-dashoffset','stroke-linecap','stroke-linejoin',
+ 'stroke-miterlimit','stroke-opacity','stroke','stroke-width','transform',
+ 'text-anchor','text-decoration','text-rendering','u1','u2','viewbox',
+ 'visibility','word-spacing','wrap','writing-mode','x','x1','x2','y',
+ 'y1','y2','z',
+
+ // MathML
+ 'accent','accentunder','bevelled','close','columnsalign','columnlines',
+ 'columnspan','denomalign','depth','display','displaystyle','fence',
+ 'frame','largeop','length','linethickness','lspace','lquote',
+ 'mathbackground','mathcolor','mathsize','mathvariant','maxsize',
+ 'minsize','movablelimits','notation','numalign','open','rowalign',
+ 'rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel',
+ 'scriptminsize','scriptsizemultiplier','selection','separator',
+ 'separators','stretchy','subscriptshift','supscriptshift','symmetric',
+ 'voffset',
+
+ // XML
+ 'xlink:href','xml:id','xlink:title','xml:space'
+ ]);
+
+ /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */
+ var FORBID_TAGS = null;
+
+ /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */
+ var FORBID_ATTR = null;
+
+ /* Decide if custom data attributes are okay */
+ var ALLOW_DATA_ATTR = true;
+
+ /* Output should be safe for jQuery's $() factory? */
+ var SAFE_FOR_JQUERY = false;
+
+ /* Decide if document with <html>... should be returned */
+ var WHOLE_DOCUMENT = false;
+
+ /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html string.
+ * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead
+ */
+ var RETURN_DOM = false;
+
+ /* Decide if a DOM `DocumentFragment` should be returned, instead of a html string */
+ var RETURN_DOM_FRAGMENT = false;
+
+ /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM
+ * `Node` is imported into the current `Document`. If this flag is not enabled the
+ * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by
+ * DOMPurify. */
+ var RETURN_DOM_IMPORT = false;
+
+ /* Output should be free from DOM clobbering attacks? */
+ var SANITIZE_DOM = true;
+
+ /* Keep element content when removing element? */
+ var KEEP_CONTENT = true;
+
+ /* Tags to ignore content of when KEEP_CONTENT is true */
+ var FORBID_CONTENTS = _addToSet({}, [
+ 'audio', 'head', 'math', 'script', 'style', 'svg', 'video'
+ ]);
+
+ /* Keep a reference to config to pass to hooks */
+ var CONFIG = null;
+
+ /* Ideally, do not touch anything below this line */
+ /* ______________________________________________ */
+
+ var formElement = document.createElement('form');
+
+ /**
+ * _parseConfig
+ *
+ * @param optional config literal
+ */
+ var _parseConfig = function(cfg) {
+ /* Shield configuration object from tampering */
+ if (typeof cfg !== 'object') {
+ cfg = {};
+ }
+
+ /* Set configuration parameters */
+ ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ?
+ _addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;
+ ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ?
+ _addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;
+ FORBID_TAGS = 'FORBID_TAGS' in cfg ?
+ _addToSet({}, cfg.FORBID_TAGS) : {};
+ FORBID_ATTR = 'FORBID_ATTR' in cfg ?
+ _addToSet({}, cfg.FORBID_ATTR) : {};
+ ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true
+ SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false
+ WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false
+ RETURN_DOM = cfg.RETURN_DOM || false; // Default false
+ RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false
+ RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false
+ SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true
+ KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true
+
+ if (RETURN_DOM_FRAGMENT) {
+ RETURN_DOM = true;
+ }
+
+ /* Merge configuration parameters */
+ if (cfg.ADD_TAGS) {
+ if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {
+ ALLOWED_TAGS = _cloneObj(ALLOWED_TAGS);
+ }
+ _addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);
+ }
+ if (cfg.ADD_ATTR) {
+ if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {
+ ALLOWED_ATTR = _cloneObj(ALLOWED_ATTR);
+ }
+ _addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);
+ }
+
+ /* Add #text in case KEEP_CONTENT is set to true */
+ if (KEEP_CONTENT) { ALLOWED_TAGS['#text'] = true; }
+
+ // Prevent further manipulation of configuration.
+ // Not available in IE8, Safari 5, etc.
+ if (Object && 'freeze' in Object) { Object.freeze(cfg); }
+
+ CONFIG = cfg;
+ };
+
+ /**
+ * _forceRemove
+ *
+ * @param a DOM node
+ */
+ var _forceRemove = function(node) {
+ try {
+ node.parentNode.removeChild(node);
+ } catch (e) {
+ node.outerHTML = '';
+ }
+ };
+
+ /**
+ * _initDocument
+ *
+ * @param a string of dirty markup
+ * @return a DOM, filled with the dirty markup
+ */
+ var _initDocument = function(dirty) {
+ /* Create new document to parse markup to */
+ var doc = implementation.createHTMLDocument('');
+
+ /* Set content */
+ var body = doc.body;
+ body.parentNode.removeChild(body.parentNode.firstElementChild);
+ body.outerHTML = dirty;
+
+ /* Work on whole document or just its body */
+ return getElementsByTagName.call(doc,
+ WHOLE_DOCUMENT ? 'html' : 'body')[0];
+ };
+
+ /**
+ * _createIterator
+ *
+ * @param document/fragment to create iterator for
+ * @return iterator instance
+ */
+ var _createIterator = function(root) {
+ return createNodeIterator.call(root.ownerDocument || root,
+ root,
+ NodeFilter.SHOW_ELEMENT
+ | NodeFilter.SHOW_COMMENT
+ | NodeFilter.SHOW_TEXT,
+ function() { return NodeFilter.FILTER_ACCEPT; },
+ false
+ );
+ };
+
+ /**
+ * _isClobbered
+ *
+ * @param element to check for clobbering attacks
+ * @return true if clobbered, false if safe
+ */
+ var _isClobbered = function(elm) {
+ if (elm instanceof Text || elm instanceof Comment) {
+ return false;
+ }
+ if ( typeof elm.nodeName !== 'string'
+ || typeof elm.textContent !== 'string'
+ || typeof elm.removeChild !== 'function'
+ || !(elm.attributes instanceof NamedNodeMap)
+ || typeof elm.removeAttribute !== 'function'
+ || typeof elm.setAttribute !== 'function'
+ ) {
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * _sanitizeElements
+ *
+ * @protect nodeName
+ * @protect textContent
+ * @protect removeChild
+ *
+ * @param node to check for permission to exist
+ * @return true if node was killed, false if left alive
+ */
+ var _sanitizeElements = function(currentNode) {
+ /* Execute a hook if present */
+ _executeHook('beforeSanitizeElements', currentNode, null);
+
+ /* Check if element is clobbered or can clobber */
+ if (_isClobbered(currentNode)) {
+ _forceRemove(currentNode);
+ return true;
+ }
+
+ /* Now let's check the element's type and name */
+ var tagName = currentNode.nodeName.toLowerCase();
+
+ /* Execute a hook if present */
+ _executeHook('uponSanitizeElement', currentNode, {
+ tagName: tagName
+ });
+
+ /* Remove element if anything forbids its presence */
+ if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {
+ /* Keep content except for black-listed elements */
+ if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]
+ && typeof currentNode.insertAdjacentHTML === 'function') {
+ try {
+ currentNode.insertAdjacentHTML('AfterEnd', currentNode.innerHTML);
+ } catch (e) {}
+ }
+ _forceRemove(currentNode);
+ return true;
+ }
+
+ /* Finally, convert markup to cover jQuery behavior */
+ if (SAFE_FOR_JQUERY && !currentNode.firstElementChild) {
+ currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');
+ }
+
+ /* Execute a hook if present */
+ _executeHook('afterSanitizeElements', currentNode, null);
+
+ return false;
+ };
+
+ /**
+ * _sanitizeAttributes
+ *
+ * @protect attributes
+ * @protect nodeName
+ * @protect removeAttribute
+ * @protect setAttribute
+ *
+ * @param node to sanitize
+ * @return void
+ */
+ var _sanitizeAttributes = function(currentNode) {
+ /* Execute a hook if present */
+ _executeHook('beforeSanitizeAttributes', currentNode, null);
+
+ var attributes = currentNode.attributes;
+
+ /* Check if we have attributes; if not we might have a text node */
+ if (!attributes) { return; }
+
+ var hookEvent = {
+ attrName: '',
+ attrValue: '',
+ keepAttr: true
+ },
+ l = attributes.length,
+ attr, name, value, lcName, idAttr;
+
+ /* Go backwards over all attributes; safely remove bad ones */
+ while (l--) {
+ attr = attributes[l];
+ name = attr.name;
+ value = attr.value;
+ lcName = name.toLowerCase();
+
+ /* Execute a hook if present */
+ hookEvent.attrName = lcName;
+ hookEvent.attrValue = value;
+ hookEvent.keepAttr = true;
+ _executeHook('uponSanitizeAttribute', currentNode, hookEvent );
+ value = hookEvent.attrValue;
+
+ /* Remove attribute */
+ // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to
+ // remove a "name" attribute from an <img> tag that has an "id"
+ // attribute at the time.
+ if (lcName === 'name' &&
+ currentNode.nodeName === 'IMG' && attributes.id) {
+ idAttr = attributes.id;
+ attributes = Array.prototype.slice.apply(attributes);
+ currentNode.removeAttribute('id');
+ currentNode.removeAttribute(name);
+ if (attributes.indexOf(idAttr) > l) {
+ currentNode.setAttribute('id', idAttr.value);
+ }
+ } else {
+ currentNode.removeAttribute(name);
+ }
+
+ /* Did the hooks approve of the attribute? */
+ if (!hookEvent.keepAttr) {
+ continue;
+ }
+
+ /* Make sure attribute cannot clobber */
+ if (SANITIZE_DOM &&
+ (lcName === 'id' || lcName === 'name') &&
+ (value in window || value in document || value in formElement)) {
+ continue;
+ }
+
+ if (
+ /* Check the name is permitted */
+ (
+ (ALLOWED_ATTR[lcName] && !FORBID_ATTR[lcName]) ||
+ /* Allow potentially valid data-* attributes
+ * At least one character after "-" (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)
+ * XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804) */
+ (ALLOW_DATA_ATTR && DATA_ATTR.test(lcName))
+ ) &&
+ /* Get rid of script and data URIs */
+ (
+ !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE,'')) ||
+ /* Keep image data URIs alive if src is allowed */
+ (lcName === 'src' && value.indexOf('data:') === 0 &&
+ currentNode.nodeName === 'IMG')
+ )
+ ) {
+ /* Handle invalid data-* attribute set by try-catching it */
+ try {
+ currentNode.setAttribute(name, value);
+ } catch (e) {}
+ }
+ }
+
+ /* Execute a hook if present */
+ _executeHook('afterSanitizeAttributes', currentNode, null);
+ };
+ var DATA_ATTR = /^data-[\w.\u00B7-\uFFFF-]/;
+ var IS_SCRIPT_OR_DATA = /^(?:\w+script|data):/i;
+ /* This needs to be extensive thanks to Webkit/Blink's behavior */
+ var ATTR_WHITESPACE = /[\x00-\x20\xA0\u1680\u180E\u2000-\u2029\u205f\u3000]/g;
+
+ /**
+ * _sanitizeShadowDOM
+ *
+ * @param fragment to iterate over recursively
+ * @return void
+ */
+ var _sanitizeShadowDOM = function(fragment) {
+ var shadowNode;
+ var shadowIterator = _createIterator(fragment);
+
+ /* Execute a hook if present */
+ _executeHook('beforeSanitizeShadowDOM', fragment, null);
+
+ while ( (shadowNode = shadowIterator.nextNode()) ) {
+ /* Execute a hook if present */
+ _executeHook('uponSanitizeShadowNode', shadowNode, null);
+
+ /* Sanitize tags and elements */
+ if (_sanitizeElements(shadowNode)) {
+ continue;
+ }
+
+ /* Deep shadow DOM detected */
+ if (shadowNode.content instanceof DocumentFragment) {
+ _sanitizeShadowDOM(shadowNode.content);
+ }
+
+ /* Check attributes, sanitize if necessary */
+ _sanitizeAttributes(shadowNode);
+ }
+
+ /* Execute a hook if present */
+ _executeHook('afterSanitizeShadowDOM', fragment, null);
+ };
+
+ /**
+ * _executeHook
+ * Execute user configurable hooks
+ *
+ * @param {String} entryPoint Name of the hook's entry point
+ * @param {Node} currentNode
+ */
+ var _executeHook = function(entryPoint, currentNode, data) {
+ if (!hooks[entryPoint]) { return; }
+
+ hooks[entryPoint].forEach(function(hook) {
+ hook.call(DOMPurify, currentNode, data, CONFIG);
+ });
+ };
+
+ /**
+ * sanitize
+ * Public method providing core sanitation functionality
+ *
+ * @param {String} dirty string
+ * @param {Object} configuration object
+ */
+ DOMPurify.sanitize = function(dirty, cfg) {
+ /* Check we can run. Otherwise fall back or ignore */
+ if (!DOMPurify.isSupported) {
+ if (typeof window.toStaticHTML === 'function' && typeof dirty === 'string') {
+ return window.toStaticHTML(dirty);
+ }
+ return dirty;
+ }
+
+ /* Assign config vars */
+ _parseConfig(cfg);
+
+ /* Exit directly if we have nothing to do */
+ if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {
+ return dirty;
+ }
+
+ /* Initialize the document to work on */
+ var body = _initDocument(dirty);
+
+ /* Check we have a DOM node from the data */
+ if (!body) {
+ return RETURN_DOM ? null : '';
+ }
+
+ /* Get node iterator */
+ var currentNode;
+ var nodeIterator = _createIterator(body);
+
+ /* Now start iterating over the created document */
+ while ( (currentNode = nodeIterator.nextNode()) ) {
+ /* Sanitize tags and elements */
+ if (_sanitizeElements(currentNode)) {
+ continue;
+ }
+
+ /* Shadow DOM detected, sanitize it */
+ if (currentNode.content instanceof DocumentFragment) {
+ _sanitizeShadowDOM(currentNode.content);
+ }
+
+ /* Check attributes, sanitize if necessary */
+ _sanitizeAttributes(currentNode);
+ }
+
+ /* Return sanitized string or DOM */
+ var returnNode;
+ if (RETURN_DOM) {
+
+ if (RETURN_DOM_FRAGMENT) {
+ returnNode = createDocumentFragment.call(body.ownerDocument);
+
+ while (body.firstChild) {
+ returnNode.appendChild(body.firstChild);
+ }
+ } else {
+ returnNode = body;
+ }
+
+ if (RETURN_DOM_IMPORT) {
+ /* adoptNode() is not used because internal state is not reset
+ (e.g. the past names map of a HTMLFormElement), this is safe
+ in theory but we would rather not risk another attack vector.
+ The state that is cloned by importNode() is explicitly defined
+ by the specs. */
+ returnNode = importNode.call(originalDocument, returnNode, true);
+ }
+
+ return returnNode;
+ }
+
+ return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;
+ };
+
+ /**
+ * addHook
+ * Public method to add DOMPurify hooks
+ *
+ * @param {String} entryPoint
+ * @param {Function} hookFunction
+ */
+ DOMPurify.addHook = function(entryPoint, hookFunction) {
+ if (typeof hookFunction !== 'function') { return; }
+ hooks[entryPoint] = hooks[entryPoint] || [];
+ hooks[entryPoint].push(hookFunction);
+ };
+
+ /**
+ * removeHook
+ * Public method to remove a DOMPurify hook at a given entryPoint
+ * (pops it from the stack of hooks if more are present)
+ *
+ * @param {String} entryPoint
+ * @return void
+ */
+ DOMPurify.removeHook = function(entryPoint) {
+ if (hooks[entryPoint]) {
+ hooks[entryPoint].pop();
+ }
+ };
+
+ /**
+ * removeHooks
+ * Public method to remove all DOMPurify hooks at a given entryPoint
+ *
+ * @param {String} entryPoint
+ * @return void
+ */
+ DOMPurify.removeHooks = function(entryPoint) {
+ if (hooks[entryPoint]) {
+ hooks[entryPoint] = [];
+ }
+ };
+
+ /**
+ * removeAllHooks
+ * Public method to remove all DOMPurify hooks
+ *
+ * @return void
+ */
+ DOMPurify.removeAllHooks = function() {
+ hooks = [];
+ };
+
+ return DOMPurify;
+}));
diff --git a/js/vendor/eventsource-polyfill/.bower.json b/js/vendor/eventsource-polyfill/.bower.json
deleted file mode 100644
index 86a5d3d5..00000000
--- a/js/vendor/eventsource-polyfill/.bower.json
+++ /dev/null
@@ -1,43 +0,0 @@
-{
- "name": "eventsource-polyfill",
- "homepage": "https://github.com/amvtek/EventSource",
- "authors": [
- "amvtek <devel@amvtek.com>"
- ],
- "description": "A polyfill for http://www.w3.org/TR/eventsource/",
- "main": [
- "javascript/src/eventsource.js",
- "eventsource.min.js",
- "README.rst"
- ],
- "keywords": [
- "sse",
- "server sent events",
- "eventsource",
- "event-source",
- "polyfill"
- ],
- "license": "MIT",
- "ignore": [
- "**/.*",
- "javascript",
- "test_server",
- "Gruntfile.js",
- "package.json",
- "node_modules",
- "bower_components",
- "test",
- "tests",
- "docs"
- ],
- "version": "0.9.7",
- "_release": "0.9.7",
- "_resolution": {
- "type": "version",
- "tag": "v0.9.7",
- "commit": "32c3cfc08b2a3a84a6533063fee823e62987000f"
- },
- "_source": "git://github.com/amvtek/EventSource.git",
- "_target": "~0.*",
- "_originalSource": "eventsource-polyfill"
-} \ No newline at end of file
diff --git a/js/vendor/eventsource-polyfill/LICENSE b/js/vendor/eventsource-polyfill/LICENSE
deleted file mode 100644
index 62758d3f..00000000
--- a/js/vendor/eventsource-polyfill/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2014 AmvTek
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE. \ No newline at end of file
diff --git a/js/vendor/eventsource-polyfill/README.md b/js/vendor/eventsource-polyfill/README.md
deleted file mode 100644
index c949243e..00000000
--- a/js/vendor/eventsource-polyfill/README.md
+++ /dev/null
@@ -1,75 +0,0 @@
-EventSource Polyfill
-====================
-
-Provide polyfill to support EventSource in browser where it is not available.
-
-> - Used in production
-> - Tested in Internet Explorer 8 +
-> - Tested in Android browser 2.1 +
-> - [Documented][]
-> - Run the [Browser test suite][]
-
-Installing
-----------
-
-### from source
-
-Download suitable project archive (zip or tar.gz) from [release page][]
-
-Include in your html documents one of the following javascript file:
-
-> - *dist/eventsource.js*
-> - *dist/eventsource.min.js* (minified version)
-
-### Using bower package manager
-
-To install package from **bower registry**, type :
-
- bower install eventsource-polyfill
-
-Include in your html documents one of the following javascript file:
-
-> - *bower\_components/eventsource-polyfill/dist/eventsource.js*
-> - *bower\_components/eventsource-polyfill/dist/eventsource.min.js* (minified version)
-
-### Using npm package manager
-
-To install package from **npm registry**, type :
-
- npm install eventsource-polyfill
-
-Note that this package may only be used with in **browser application**.
-
-If you are using [browserify][] , you just have to require this package in your main module…
-
-``` sourceCode
-// load (Polyfill) EventSource, in case browser does not support it...
-require('eventsource-polyfill');
-```
-
-Run the tests now
------------------
-
-With your web browser visit this [test site][Browser test suite]
-
-Allow **sufficient time** ( ~ 5 minutes) for the full Test Suite to run…
-
-Project content
----------------
-
-dist/
- built version of javascript modules
-
-javascript/
- Contains polyfill module and related unit tests
-
-test_server/
- python server which generates *easy to test* **event stream**
-
-docs/
- documentation wiki
-
- [Documented]: https://github.com/amvtek/EventSource/wiki
- [Browser test suite]: http://testevs.amvtek.com/
- [release page]: https://github.com/amvtek/EventSource/releases/latest
- [browserify]: http://browserify.org
diff --git a/js/vendor/eventsource-polyfill/bower.json b/js/vendor/eventsource-polyfill/bower.json
deleted file mode 100644
index d2722f92..00000000
--- a/js/vendor/eventsource-polyfill/bower.json
+++ /dev/null
@@ -1,29 +0,0 @@
-{
- "name": "eventsource-polyfill",
- "homepage": "https://github.com/amvtek/EventSource",
- "authors": [
- "amvtek <devel@amvtek.com>"
- ],
- "description": "A polyfill for http://www.w3.org/TR/eventsource/",
- "main": ["javascript/src/eventsource.js", "eventsource.min.js", "README.rst"],
- "keywords": [
- "sse",
- "server sent events",
- "eventsource",
- "event-source",
- "polyfill"
- ],
- "license": "MIT",
- "ignore": [
- "**/.*",
- "javascript",
- "test_server",
- "Gruntfile.js",
- "package.json",
- "node_modules",
- "bower_components",
- "test",
- "tests",
- "docs"
- ]
-}
diff --git a/js/vendor/eventsource-polyfill/dist/browserify-eventsource.js b/js/vendor/eventsource-polyfill/dist/browserify-eventsource.js
deleted file mode 100644
index 76b9b4ad..00000000
--- a/js/vendor/eventsource-polyfill/dist/browserify-eventsource.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * CommonJS module that exports EventSource polyfill version 0.9.7
- * This module is intended for browser side use
- * =====================================================================
- * THIS IS A POLYFILL MODULE, SO IT HAS SIDE EFFECTS
- * IT AUTOMATICALLY CHECKS IF window OBJECT DEFINES EventSource
- * AND ADD THE EXPORTED ONE IN CASE IT IS UNDEFINED
- * =====================================================================
- * Supported by sc AmvTek srl
- * :email: devel@amvtek.com
- */
-
-
-var PolyfillEventSource = require('./eventsource.js').EventSource;
-module.exports = PolyfillEventSource;
-
-// Add EventSource to window if it is missing...
-if (window && !window.EventSource){
- window.EventSource = PolyfillEventSource;
- if (console){
- console.log("polyfill-eventsource added missing EventSource to window");
- }
-}
diff --git a/js/vendor/eventsource-polyfill/dist/eventsource.js b/js/vendor/eventsource-polyfill/dist/eventsource.js
deleted file mode 100644
index d3b563b3..00000000
--- a/js/vendor/eventsource-polyfill/dist/eventsource.js
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- * EventSource polyfill version 0.9.7
- * Supported by sc AmvTek srl
- * :email: devel@amvtek.com
- */
-;(function (global) {
-
- if (global.EventSource && !global._eventSourceImportPrefix){
- return;
- }
-
- var evsImportName = (global._eventSourceImportPrefix||'')+"EventSource";
-
- var EventSource = function (url, options) {
-
- if (!url || typeof url != 'string') {
- throw new SyntaxError('Not enough arguments');
- }
-
- this.URL = url;
- this.setOptions(options);
- var evs = this;
- setTimeout(function(){evs.poll()}, 0);
- };
-
- EventSource.prototype = {
-
- CONNECTING: 0,
-
- OPEN: 1,
-
- CLOSED: 2,
-
- defaultOptions: {
-
- loggingEnabled: false,
-
- loggingPrefix: "eventsource",
-
- interval: 500, // milliseconds
-
- bufferSizeLimit: 256*1024, // bytes
-
- silentTimeout: 300000, // milliseconds
-
- getArgs:{
- 'evs_buffer_size_limit': 256*1024
- },
-
- xhrHeaders:{
- 'Accept': 'text/event-stream',
- 'Cache-Control': 'no-cache',
- 'X-Requested-With': 'XMLHttpRequest'
- }
- },
-
- setOptions: function(options){
-
- var defaults = this.defaultOptions;
- var option;
-
- // set all default options...
- for (option in defaults){
-
- if ( defaults.hasOwnProperty(option) ){
- this[option] = defaults[option];
- }
- }
-
- // override with what is in options
- for (option in options){
-
- if (option in defaults && options.hasOwnProperty(option)){
- this[option] = options[option];
- }
- }
-
- // if getArgs option is enabled
- // ensure evs_buffer_size_limit corresponds to bufferSizeLimit
- if (this.getArgs && this.bufferSizeLimit) {
-
- this.getArgs['evs_buffer_size_limit'] = this.bufferSizeLimit;
- }
-
- // if console is not available, force loggingEnabled to false
- if (typeof console === "undefined" || typeof console.log === "undefined") {
-
- this.loggingEnabled = false;
- }
- },
-
- log: function(message) {
-
- if (this.loggingEnabled) {
-
- console.log("[" + this.loggingPrefix +"]:" + message)
- }
- },
-
- poll: function() {
-
- try {
-
- if (this.readyState == this.CLOSED) {
- return;
- }
-
- this.cleanup();
- this.readyState = this.CONNECTING;
- this.cursor = 0;
- this.cache = '';
- this._xhr = new this.XHR(this);
- this.resetNoActivityTimer();
-
- }
- catch (e) {
-
- // in an attempt to silence the errors
- this.log('There were errors inside the pool try-catch');
- this.dispatchEvent('error', { type: 'error', data: e.message });
- }
- },
-
- pollAgain: function (interval) {
-
- // schedule poll to be called after interval milliseconds
- var evs = this;
- evs.readyState = evs.CONNECTING;
- evs.dispatchEvent('error', {
- type: 'error',
- data: "Reconnecting "
- });
- this._pollTimer = setTimeout(function(){evs.poll()}, interval||0);
- },
-
-
- cleanup: function() {
-
- this.log('evs cleaning up')
-
- if (this._pollTimer){
- clearInterval(this._pollTimer);
- this._pollTimer = null;
- }
-
- if (this._noActivityTimer){
- clearInterval(this._noActivityTimer);
- this._noActivityTimer = null;
- }
-
- if (this._xhr){
- this._xhr.abort();
- this._xhr = null;
- }
- },
-
- resetNoActivityTimer: function(){
-
- if (this.silentTimeout){
-
- if (this._noActivityTimer){
- clearInterval(this._noActivityTimer);
- }
- var evs = this;
- this._noActivityTimer = setTimeout(
- function(){ evs.log('Timeout! silentTImeout:'+evs.silentTimeout); evs.pollAgain(); },
- this.silentTimeout
- );
- }
- },
-
- close: function () {
-
- this.readyState = this.CLOSED;
- this.log('Closing connection. readyState: '+this.readyState);
- this.cleanup();
- },
-
- _onxhrdata: function() {
-
- var request = this._xhr;
-
- if (request.isReady() && !request.hasError() ) {
- // reset the timer, as we have activity
- this.resetNoActivityTimer();
-
- // move this EventSource to OPEN state...
- if (this.readyState == this.CONNECTING) {
- this.readyState = this.OPEN;
- this.dispatchEvent('open', { type: 'open' });
- }
-
- var buffer = request.getBuffer();
-
- if (buffer.length > this.bufferSizeLimit) {
- this.log('buffer.length > this.bufferSizeLimit');
- this.pollAgain();
- }
-
- if (this.cursor == 0 && buffer.length > 0){
-
- // skip byte order mark \uFEFF character if it starts the stream
- if (buffer.substring(0,1) == '\uFEFF'){
- this.cursor = 1;
- }
- }
-
- var lastMessageIndex = this.lastMessageIndex(buffer);
- if (lastMessageIndex[0] >= this.cursor){
-
- var newcursor = lastMessageIndex[1];
- var toparse = buffer.substring(this.cursor, newcursor);
- this.parseStream(toparse);
- this.cursor = newcursor;
- }
-
- // if request is finished, reopen the connection
- if (request.isDone()) {
- this.log('request.isDone(). reopening the connection');
- this.pollAgain(this.interval);
- }
- }
- else if (this.readyState !== this.CLOSED) {
-
- this.log('this.readyState !== this.CLOSED');
- this.pollAgain(this.interval);
-
- //MV: Unsure why an error was previously dispatched
- }
- },
-
- parseStream: function(chunk) {
-
- // normalize line separators (\r\n,\r,\n) to \n
- // remove white spaces that may precede \n
- chunk = this.cache + this.normalizeToLF(chunk);
-
- var events = chunk.split('\n\n');
-
- var i, j, eventType, datas, line, retry;
-
- for (i=0; i < (events.length - 1); i++) {
-
- eventType = 'message';
- datas = [];
- parts = events[i].split('\n');
-
- for (j=0; j < parts.length; j++) {
-
- line = this.trimWhiteSpace(parts[j]);
-
- if (line.indexOf('event') == 0) {
-
- eventType = line.replace(/event:?\s*/, '');
- }
- else if (line.indexOf('retry') == 0) {
-
- retry = parseInt(line.replace(/retry:?\s*/, ''));
- if(!isNaN(retry)) {
- this.interval = retry;
- }
- }
- else if (line.indexOf('data') == 0) {
-
- datas.push(line.replace(/data:?\s*/, ''));
- }
- else if (line.indexOf('id:') == 0) {
-
- this.lastEventId = line.replace(/id:?\s*/, '');
- }
- else if (line.indexOf('id') == 0) { // this resets the id
-
- this.lastEventId = null;
- }
- }
-
- if (datas.length) {
- // dispatch a new event
- var event = new MessageEvent(eventType, datas.join('\n'), window.location.origin, this.lastEventId);
- this.dispatchEvent(eventType, event);
- }
- }
-
- this.cache = events[events.length - 1];
- },
-
- dispatchEvent: function (type, event) {
- var handlers = this['_' + type + 'Handlers'];
-
- if (handlers) {
-
- for (var i = 0; i < handlers.length; i++) {
- handlers[i].call(this, event);
- }
- }
-
- if (this['on' + type]) {
- this['on' + type].call(this, event);
- }
-
- },
-
- addEventListener: function (type, handler) {
- if (!this['_' + type + 'Handlers']) {
- this['_' + type + 'Handlers'] = [];
- }
-
- this['_' + type + 'Handlers'].push(handler);
- },
-
- removeEventListener: function (type, handler) {
- var handlers = this['_' + type + 'Handlers'];
- if (!handlers) {
- return;
- }
- for (var i = handlers.length - 1; i >= 0; --i) {
- if (handlers[i] === handler) {
- handlers.splice(i, 1);
- break;
- }
- }
- },
-
- _pollTimer: null,
-
- _noactivityTimer: null,
-
- _xhr: null,
-
- lastEventId: null,
-
- cache: '',
-
- cursor: 0,
-
- onerror: null,
-
- onmessage: null,
-
- onopen: null,
-
- readyState: 0,
-
- // ===================================================================
- // helpers functions
- // those are attached to prototype to ease reuse and testing...
-
- urlWithParams: function (baseURL, params) {
-
- var encodedArgs = [];
-
- if (params){
-
- var key, urlarg;
- var urlize = encodeURIComponent;
-
- for (key in params){
- if (params.hasOwnProperty(key)) {
- urlarg = urlize(key)+'='+urlize(params[key]);
- encodedArgs.push(urlarg);
- }
- }
- }
-
- if (encodedArgs.length > 0){
-
- if (baseURL.indexOf('?') == -1)
- return baseURL + '?' + encodedArgs.join('&');
- return baseURL + '&' + encodedArgs.join('&');
- }
- return baseURL;
- },
-
- lastMessageIndex: function(text) {
-
- var ln2 =text.lastIndexOf('\n\n');
- var lr2 = text.lastIndexOf('\r\r');
- var lrln2 = text.lastIndexOf('\r\n\r\n');
-
- if (lrln2 > Math.max(ln2, lr2)) {
- return [lrln2, lrln2+4];
- }
- return [Math.max(ln2, lr2), Math.max(ln2, lr2) + 2]
- },
-
- trimWhiteSpace: function(str) {
- // to remove whitespaces left and right of string
-
- var reTrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
- return str.replace(reTrim, '');
- },
-
- normalizeToLF: function(str) {
-
- // replace \r and \r\n with \n
- return str.replace(/\r\n|\r/g, '\n');
- }
-
- };
-
- if (!isOldIE()){
-
- EventSource.isPolyfill = "XHR";
-
- // EventSource will send request using XMLHttpRequest
- EventSource.prototype.XHR = function(evs) {
-
- request = new XMLHttpRequest();
- this._request = request;
- evs._xhr = this;
-
- // set handlers
- request.onreadystatechange = function(){
- if (request.readyState > 1 && evs.readyState != evs.CLOSED) {
- if (request.status == 200 || (request.status>=300 && request.status<400)){
- evs._onxhrdata();
- }
- else {
- request._failed = true;
- evs.readyState = evs.CLOSED;
- evs.dispatchEvent('error', {
- type: 'error',
- data: "The server responded with "+request.status
- });
- evs.close();
- }
- }
- };
-
- request.onprogress = function () {
- };
-
- request.open('GET', evs.urlWithParams(evs.URL, evs.getArgs), true);
-
- var headers = evs.xhrHeaders; // maybe null
- for (var header in headers) {
- if (headers.hasOwnProperty(header)){
- request.setRequestHeader(header, headers[header]);
- }
- }
- if (evs.lastEventId) {
- request.setRequestHeader('Last-Event-Id', evs.lastEventId);
- }
-
- request.send();
- };
-
- EventSource.prototype.XHR.prototype = {
-
- useXDomainRequest: false,
-
- _request: null,
-
- _failed: false, // true if we have had errors...
-
- isReady: function() {
-
-
- return this._request.readyState >= 2;
- },
-
- isDone: function() {
-
- return (this._request.readyState == 4);
- },
-
- hasError: function() {
-
- return (this._failed || (this._request.status >= 400));
- },
-
- getBuffer: function() {
-
- var rv = '';
- try {
- rv = this._request.responseText || '';
- }
- catch (e){}
- return rv;
- },
-
- abort: function() {
-
- if ( this._request ) {
- this._request.abort();
- }
- }
- };
- }
- else {
-
- EventSource.isPolyfill = "IE_8-9";
-
- // patch EventSource defaultOptions
- var defaults = EventSource.prototype.defaultOptions;
- defaults.xhrHeaders = null; // no headers will be sent
- defaults.getArgs['evs_preamble'] = 2048 + 8;
-
- // EventSource will send request using Internet Explorer XDomainRequest
- EventSource.prototype.XHR = function(evs) {
-
- request = new XDomainRequest();
- this._request = request;
-
- // set handlers
- request.onprogress = function(){
- request._ready = true;
- evs._onxhrdata();
- };
-
- request.onload = function(){
- this._loaded = true;
- evs._onxhrdata();
- };
-
- request.onerror = function(){
- this._failed = true;
- evs.readyState = evs.CLOSED;
- evs.dispatchEvent('error', {
- type: 'error',
- data: "XDomainRequest error"
- });
- };
-
- request.ontimeout = function(){
- this._failed = true;
- evs.readyState = evs.CLOSED;
- evs.dispatchEvent('error', {
- type: 'error',
- data: "XDomainRequest timed out"
- });
- };
-
- // XDomainRequest does not allow setting custom headers
- // If EventSource has enabled the use of GET arguments
- // we add parameters to URL so that server can adapt the stream...
- var reqGetArgs = {};
- if (evs.getArgs) {
-
- // copy evs.getArgs in reqGetArgs
- var defaultArgs = evs.getArgs;
- for (var key in defaultArgs) {
- if (defaultArgs.hasOwnProperty(key)){
- reqGetArgs[key] = defaultArgs[key];
- }
- }
- if (evs.lastEventId){
- reqGetArgs['evs_last_event_id'] = evs.lastEventId;
- }
- }
- // send the request
-
- request.open('GET', evs.urlWithParams(evs.URL,reqGetArgs));
- request.send();
- };
-
- EventSource.prototype.XHR.prototype = {
-
- useXDomainRequest: true,
-
- _request: null,
-
- _ready: false, // true when progress events are dispatched
-
- _loaded: false, // true when request has been loaded
-
- _failed: false, // true if when request is in error
-
- isReady: function() {
-
- return this._request._ready;
- },
-
- isDone: function() {
-
- return this._request._loaded;
- },
-
- hasError: function() {
-
- return this._request._failed;
- },
-
- getBuffer: function() {
-
- var rv = '';
- try {
- rv = this._request.responseText || '';
- }
- catch (e){}
- return rv;
- },
-
- abort: function() {
-
- if ( this._request){
- this._request.abort();
- }
- }
- };
- }
-
- function MessageEvent(type, data, origin, lastEventId) {
-
- this.bubbles = false;
- this.cancelBubble = false;
- this.cancelable = false;
- this.data = data || null;
- this.origin = origin || '';
- this.lastEventId = lastEventId || '';
- this.type = type || 'message';
- }
-
- function isOldIE () {
-
- //return true if we are in IE8 or IE9
- return (window.XDomainRequest && (window.XMLHttpRequest && new XMLHttpRequest().responseType === undefined)) ? true : false;
- }
-
- global[evsImportName] = EventSource;
-})(this);
diff --git a/js/vendor/eventsource-polyfill/dist/eventsource.min.js b/js/vendor/eventsource-polyfill/dist/eventsource.min.js
deleted file mode 100644
index 3e79de63..00000000
--- a/js/vendor/eventsource-polyfill/dist/eventsource.min.js
+++ /dev/null
@@ -1 +0,0 @@
-!function(a){function b(a,b,c,d){this.bubbles=!1,this.cancelBubble=!1,this.cancelable=!1,this.data=b||null,this.origin=c||"",this.lastEventId=d||"",this.type=a||"message"}function c(){return window.XDomainRequest&&window.XMLHttpRequest&&void 0===(new XMLHttpRequest).responseType?!0:!1}if(!a.EventSource||a._eventSourceImportPrefix){var d=(a._eventSourceImportPrefix||"")+"EventSource",e=function(a,b){if(!a||"string"!=typeof a)throw new SyntaxError("Not enough arguments");this.URL=a,this.setOptions(b);var c=this;setTimeout(function(){c.poll()},0)};if(e.prototype={CONNECTING:0,OPEN:1,CLOSED:2,defaultOptions:{loggingEnabled:!1,loggingPrefix:"eventsource",interval:500,bufferSizeLimit:262144,silentTimeout:3e5,getArgs:{evs_buffer_size_limit:262144},xhrHeaders:{Accept:"text/event-stream","Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"}},setOptions:function(a){var b,c=this.defaultOptions;for(b in c)c.hasOwnProperty(b)&&(this[b]=c[b]);for(b in a)b in c&&a.hasOwnProperty(b)&&(this[b]=a[b]);this.getArgs&&this.bufferSizeLimit&&(this.getArgs.evs_buffer_size_limit=this.bufferSizeLimit),("undefined"==typeof console||"undefined"==typeof console.log)&&(this.loggingEnabled=!1)},log:function(a){this.loggingEnabled&&console.log("["+this.loggingPrefix+"]:"+a)},poll:function(){try{if(this.readyState==this.CLOSED)return;this.cleanup(),this.readyState=this.CONNECTING,this.cursor=0,this.cache="",this._xhr=new this.XHR(this),this.resetNoActivityTimer()}catch(a){this.log("There were errors inside the pool try-catch"),this.dispatchEvent("error",{type:"error",data:a.message})}},pollAgain:function(a){var b=this;b.readyState=b.CONNECTING,b.dispatchEvent("error",{type:"error",data:"Reconnecting "}),this._pollTimer=setTimeout(function(){b.poll()},a||0)},cleanup:function(){this.log("evs cleaning up"),this._pollTimer&&(clearInterval(this._pollTimer),this._pollTimer=null),this._noActivityTimer&&(clearInterval(this._noActivityTimer),this._noActivityTimer=null),this._xhr&&(this._xhr.abort(),this._xhr=null)},resetNoActivityTimer:function(){if(this.silentTimeout){this._noActivityTimer&&clearInterval(this._noActivityTimer);var a=this;this._noActivityTimer=setTimeout(function(){a.log("Timeout! silentTImeout:"+a.silentTimeout),a.pollAgain()},this.silentTimeout)}},close:function(){this.readyState=this.CLOSED,this.log("Closing connection. readyState: "+this.readyState),this.cleanup()},_onxhrdata:function(){var a=this._xhr;if(a.isReady()&&!a.hasError()){this.resetNoActivityTimer(),this.readyState==this.CONNECTING&&(this.readyState=this.OPEN,this.dispatchEvent("open",{type:"open"}));var b=a.getBuffer();b.length>this.bufferSizeLimit&&(this.log("buffer.length > this.bufferSizeLimit"),this.pollAgain()),0==this.cursor&&b.length>0&&""==b.substring(0,1)&&(this.cursor=1);var c=this.lastMessageIndex(b);if(c[0]>=this.cursor){var d=c[1],e=b.substring(this.cursor,d);this.parseStream(e),this.cursor=d}a.isDone()&&(this.log("request.isDone(). reopening the connection"),this.pollAgain(this.interval))}else this.readyState!==this.CLOSED&&(this.log("this.readyState !== this.CLOSED"),this.pollAgain(this.interval))},parseStream:function(a){a=this.cache+this.normalizeToLF(a);var c,d,e,f,g,h,i=a.split("\n\n");for(c=0;c<i.length-1;c++){for(e="message",f=[],parts=i[c].split("\n"),d=0;d<parts.length;d++)g=this.trimWhiteSpace(parts[d]),0==g.indexOf("event")?e=g.replace(/event:?\s*/,""):0==g.indexOf("retry")?(h=parseInt(g.replace(/retry:?\s*/,"")),isNaN(h)||(this.interval=h)):0==g.indexOf("data")?f.push(g.replace(/data:?\s*/,"")):0==g.indexOf("id:")?this.lastEventId=g.replace(/id:?\s*/,""):0==g.indexOf("id")&&(this.lastEventId=null);if(f.length){var j=new b(e,f.join("\n"),window.location.origin,this.lastEventId);this.dispatchEvent(e,j)}}this.cache=i[i.length-1]},dispatchEvent:function(a,b){var c=this["_"+a+"Handlers"];if(c)for(var d=0;d<c.length;d++)c[d].call(this,b);this["on"+a]&&this["on"+a].call(this,b)},addEventListener:function(a,b){this["_"+a+"Handlers"]||(this["_"+a+"Handlers"]=[]),this["_"+a+"Handlers"].push(b)},removeEventListener:function(a,b){var c=this["_"+a+"Handlers"];if(c)for(var d=c.length-1;d>=0;--d)if(c[d]===b){c.splice(d,1);break}},_pollTimer:null,_noactivityTimer:null,_xhr:null,lastEventId:null,cache:"",cursor:0,onerror:null,onmessage:null,onopen:null,readyState:0,urlWithParams:function(a,b){var c=[];if(b){var d,e,f=encodeURIComponent;for(d in b)b.hasOwnProperty(d)&&(e=f(d)+"="+f(b[d]),c.push(e))}return c.length>0?-1==a.indexOf("?")?a+"?"+c.join("&"):a+"&"+c.join("&"):a},lastMessageIndex:function(a){var b=a.lastIndexOf("\n\n"),c=a.lastIndexOf("\r\r"),d=a.lastIndexOf("\r\n\r\n");return d>Math.max(b,c)?[d,d+4]:[Math.max(b,c),Math.max(b,c)+2]},trimWhiteSpace:function(a){var b=/^(\s|\u00A0)+|(\s|\u00A0)+$/g;return a.replace(b,"")},normalizeToLF:function(a){return a.replace(/\r\n|\r/g,"\n")}},c()){e.isPolyfill="IE_8-9";var f=e.prototype.defaultOptions;f.xhrHeaders=null,f.getArgs.evs_preamble=2056,e.prototype.XHR=function(a){request=new XDomainRequest,this._request=request,request.onprogress=function(){request._ready=!0,a._onxhrdata()},request.onload=function(){this._loaded=!0,a._onxhrdata()},request.onerror=function(){this._failed=!0,a.readyState=a.CLOSED,a.dispatchEvent("error",{type:"error",data:"XDomainRequest error"})},request.ontimeout=function(){this._failed=!0,a.readyState=a.CLOSED,a.dispatchEvent("error",{type:"error",data:"XDomainRequest timed out"})};var b={};if(a.getArgs){var c=a.getArgs;for(var d in c)c.hasOwnProperty(d)&&(b[d]=c[d]);a.lastEventId&&(b.evs_last_event_id=a.lastEventId)}request.open("GET",a.urlWithParams(a.URL,b)),request.send()},e.prototype.XHR.prototype={useXDomainRequest:!0,_request:null,_ready:!1,_loaded:!1,_failed:!1,isReady:function(){return this._request._ready},isDone:function(){return this._request._loaded},hasError:function(){return this._request._failed},getBuffer:function(){var a="";try{a=this._request.responseText||""}catch(b){}return a},abort:function(){this._request&&this._request.abort()}}}else e.isPolyfill="XHR",e.prototype.XHR=function(a){request=new XMLHttpRequest,this._request=request,a._xhr=this,request.onreadystatechange=function(){request.readyState>1&&a.readyState!=a.CLOSED&&(200==request.status||request.status>=300&&request.status<400?a._onxhrdata():(request._failed=!0,a.readyState=a.CLOSED,a.dispatchEvent("error",{type:"error",data:"The server responded with "+request.status}),a.close()))},request.onprogress=function(){},request.open("GET",a.urlWithParams(a.URL,a.getArgs),!0);var b=a.xhrHeaders;for(var c in b)b.hasOwnProperty(c)&&request.setRequestHeader(c,b[c]);a.lastEventId&&request.setRequestHeader("Last-Event-Id",a.lastEventId),request.send()},e.prototype.XHR.prototype={useXDomainRequest:!1,_request:null,_failed:!1,isReady:function(){return this._request.readyState>=2},isDone:function(){return 4==this._request.readyState},hasError:function(){return this._failed||this._request.status>=400},getBuffer:function(){var a="";try{a=this._request.responseText||""}catch(b){}return a},abort:function(){this._request&&this._request.abort()}};a[d]=e}}(this); \ No newline at end of file
diff --git a/js/vendor/github-markdown-css/.bower.json b/js/vendor/github-markdown-css/.bower.json
deleted file mode 100644
index bff2cb88..00000000
--- a/js/vendor/github-markdown-css/.bower.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "name": "github-markdown-css",
- "description": "The minimal amount of CSS to replicate the GitHub Markdown style",
- "license": "MIT",
- "main": "github-markdown.css",
- "keywords": [
- "github",
- "markdown",
- "md",
- "css",
- "style",
- "stylesheet"
- ],
- "ignore": [
- "**/.*",
- "package.json",
- "index.html"
- ],
- "homepage": "https://github.com/sindresorhus/github-markdown-css",
- "version": "2.0.9",
- "_release": "2.0.9",
- "_resolution": {
- "type": "version",
- "tag": "2.0.9",
- "commit": "0d3c28edca0b172140af74c191f7a0c15703c10a"
- },
- "_source": "git://github.com/sindresorhus/github-markdown-css.git",
- "_target": "~2.*",
- "_originalSource": "github-markdown-css"
-} \ No newline at end of file
diff --git a/js/vendor/github-markdown-css/bower.json b/js/vendor/github-markdown-css/bower.json
deleted file mode 100644
index 6b164322..00000000
--- a/js/vendor/github-markdown-css/bower.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- "name": "github-markdown-css",
- "description": "The minimal amount of CSS to replicate the GitHub Markdown style",
- "license": "MIT",
- "main": "github-markdown.css",
- "keywords": [
- "github",
- "markdown",
- "md",
- "css",
- "style",
- "stylesheet"
- ],
- "ignore": [
- "**/.*",
- "package.json",
- "index.html"
- ]
-}
diff --git a/js/vendor/github-markdown-css/github-markdown.css b/js/vendor/github-markdown-css/github-markdown.css
deleted file mode 100644
index 5d9445ce..00000000
--- a/js/vendor/github-markdown-css/github-markdown.css
+++ /dev/null
@@ -1,649 +0,0 @@
-@font-face {
- font-family: octicons-anchor;
- src: url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAYcAA0AAAAACjQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABMAAAABwAAAAca8vGTk9TLzIAAAFMAAAARAAAAFZG1VHVY21hcAAAAZAAAAA+AAABQgAP9AdjdnQgAAAB0AAAAAQAAAAEACICiGdhc3AAAAHUAAAACAAAAAj//wADZ2x5ZgAAAdwAAADRAAABEKyikaNoZWFkAAACsAAAAC0AAAA2AtXoA2hoZWEAAALgAAAAHAAAACQHngNFaG10eAAAAvwAAAAQAAAAEAwAACJsb2NhAAADDAAAAAoAAAAKALIAVG1heHAAAAMYAAAAHwAAACABEAB2bmFtZQAAAzgAAALBAAAFu3I9x/Nwb3N0AAAF/AAAAB0AAAAvaoFvbwAAAAEAAAAAzBdyYwAAAADP2IQvAAAAAM/bz7t4nGNgZGFgnMDAysDB1Ml0hoGBoR9CM75mMGLkYGBgYmBlZsAKAtJcUxgcPsR8iGF2+O/AEMPsznAYKMwIkgMA5REMOXicY2BgYGaAYBkGRgYQsAHyGMF8FgYFIM0ChED+h5j//yEk/3KoSgZGNgYYk4GRCUgwMaACRoZhDwCs7QgGAAAAIgKIAAAAAf//AAJ4nHWMMQrCQBBF/0zWrCCIKUQsTDCL2EXMohYGSSmorScInsRGL2DOYJe0Ntp7BK+gJ1BxF1stZvjz/v8DRghQzEc4kIgKwiAppcA9LtzKLSkdNhKFY3HF4lK69ExKslx7Xa+vPRVS43G98vG1DnkDMIBUgFN0MDXflU8tbaZOUkXUH0+U27RoRpOIyCKjbMCVejwypzJJG4jIwb43rfl6wbwanocrJm9XFYfskuVC5K/TPyczNU7b84CXcbxks1Un6H6tLH9vf2LRnn8Ax7A5WQAAAHicY2BkYGAA4teL1+yI57f5ysDNwgAC529f0kOmWRiYVgEpDgYmEA8AUzEKsQAAAHicY2BkYGB2+O/AEMPCAAJAkpEBFbAAADgKAe0EAAAiAAAAAAQAAAAEAAAAAAAAKgAqACoAiAAAeJxjYGRgYGBhsGFgYgABEMkFhAwM/xn0QAIAD6YBhwB4nI1Ty07cMBS9QwKlQapQW3VXySvEqDCZGbGaHULiIQ1FKgjWMxknMfLEke2A+IJu+wntrt/QbVf9gG75jK577Lg8K1qQPCfnnnt8fX1NRC/pmjrk/zprC+8D7tBy9DHgBXoWfQ44Av8t4Bj4Z8CLtBL9CniJluPXASf0Lm4CXqFX8Q84dOLnMB17N4c7tBo1AS/Qi+hTwBH4rwHHwN8DXqQ30XXAS7QaLwSc0Gn8NuAVWou/gFmnjLrEaEh9GmDdDGgL3B4JsrRPDU2hTOiMSuJUIdKQQayiAth69r6akSSFqIJuA19TrzCIaY8sIoxyrNIrL//pw7A2iMygkX5vDj+G+kuoLdX4GlGK/8Lnlz6/h9MpmoO9rafrz7ILXEHHaAx95s9lsI7AHNMBWEZHULnfAXwG9/ZqdzLI08iuwRloXE8kfhXYAvE23+23DU3t626rbs8/8adv+9DWknsHp3E17oCf+Z48rvEQNZ78paYM38qfk3v/u3l3u3GXN2Dmvmvpf1Srwk3pB/VSsp512bA/GG5i2WJ7wu430yQ5K3nFGiOqgtmSB5pJVSizwaacmUZzZhXLlZTq8qGGFY2YcSkqbth6aW1tRmlaCFs2016m5qn36SbJrqosG4uMV4aP2PHBmB3tjtmgN2izkGQyLWprekbIntJFing32a5rKWCN/SdSoga45EJykyQ7asZvHQ8PTm6cslIpwyeyjbVltNikc2HTR7YKh9LBl9DADC0U/jLcBZDKrMhUBfQBvXRzLtFtjU9eNHKin0x5InTqb8lNpfKv1s1xHzTXRqgKzek/mb7nB8RZTCDhGEX3kK/8Q75AmUM/eLkfA+0Hi908Kx4eNsMgudg5GLdRD7a84npi+YxNr5i5KIbW5izXas7cHXIMAau1OueZhfj+cOcP3P8MNIWLyYOBuxL6DRylJ4cAAAB4nGNgYoAALjDJyIAOWMCiTIxMLDmZedkABtIBygAAAA==) format('woff');
-}
-
-.markdown-body {
- -webkit-text-size-adjust: 100%;
- -ms-text-size-adjust: 100%;
- text-size-adjust: 100%;
- color: #333;
- overflow: hidden;
- font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
- font-size: 16px;
- line-height: 1.6;
- word-wrap: break-word;
-}
-
-.markdown-body a {
- background-color: transparent;
-}
-
-.markdown-body a:active,
-.markdown-body a:hover {
- outline: 0;
-}
-
-.markdown-body strong {
- font-weight: bold;
-}
-
-.markdown-body h1 {
- font-size: 2em;
- margin: 0.67em 0;
-}
-
-.markdown-body img {
- border: 0;
-}
-
-.markdown-body hr {
- box-sizing: content-box;
- height: 0;
-}
-
-.markdown-body pre {
- overflow: auto;
-}
-
-.markdown-body code,
-.markdown-body kbd,
-.markdown-body pre {
- font-family: monospace, monospace;
- font-size: 1em;
-}
-
-.markdown-body input {
- color: inherit;
- font: inherit;
- margin: 0;
-}
-
-.markdown-body html input[disabled] {
- cursor: default;
-}
-
-.markdown-body input {
- line-height: normal;
-}
-
-.markdown-body input[type="checkbox"] {
- box-sizing: border-box;
- padding: 0;
-}
-
-.markdown-body table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-.markdown-body td,
-.markdown-body th {
- padding: 0;
-}
-
-.markdown-body * {
- box-sizing: border-box;
-}
-
-.markdown-body input {
- font: 13px/1.4 Helvetica, arial, nimbussansl, liberationsans, freesans, clean, sans-serif, "Segoe UI Emoji", "Segoe UI Symbol";
-}
-
-.markdown-body a {
- color: #4078c0;
- text-decoration: none;
-}
-
-.markdown-body a:hover,
-.markdown-body a:active {
- text-decoration: underline;
-}
-
-.markdown-body hr {
- height: 0;
- margin: 15px 0;
- overflow: hidden;
- background: transparent;
- border: 0;
- border-bottom: 1px solid #ddd;
-}
-
-.markdown-body hr:before {
- display: table;
- content: "";
-}
-
-.markdown-body hr:after {
- display: table;
- clear: both;
- content: "";
-}
-
-.markdown-body h1,
-.markdown-body h2,
-.markdown-body h3,
-.markdown-body h4,
-.markdown-body h5,
-.markdown-body h6 {
- margin-top: 15px;
- margin-bottom: 15px;
- line-height: 1.1;
-}
-
-.markdown-body h1 {
- font-size: 30px;
-}
-
-.markdown-body h2 {
- font-size: 21px;
-}
-
-.markdown-body h3 {
- font-size: 16px;
-}
-
-.markdown-body h4 {
- font-size: 14px;
-}
-
-.markdown-body h5 {
- font-size: 12px;
-}
-
-.markdown-body h6 {
- font-size: 11px;
-}
-
-.markdown-body blockquote {
- margin: 0;
-}
-
-.markdown-body ul,
-.markdown-body ol {
- padding: 0;
- margin-top: 0;
- margin-bottom: 0;
-}
-
-.markdown-body ol ol,
-.markdown-body ul ol {
- list-style-type: lower-roman;
-}
-
-.markdown-body ul ul ol,
-.markdown-body ul ol ol,
-.markdown-body ol ul ol,
-.markdown-body ol ol ol {
- list-style-type: lower-alpha;
-}
-
-.markdown-body dd {
- margin-left: 0;
-}
-
-.markdown-body code {
- font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
- font-size: 12px;
-}
-
-.markdown-body pre {
- margin-top: 0;
- margin-bottom: 0;
- font: 12px Consolas, "Liberation Mono", Menlo, Courier, monospace;
-}
-
-.markdown-body .octicon {
- font: normal normal normal 16px/1 octicons-anchor;
- display: inline-block;
- text-decoration: none;
- text-rendering: auto;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-
-.markdown-body .octicon-link:before {
- content: '\f05c';
-}
-
-.markdown-body>*:first-child {
- margin-top: 0 !important;
-}
-
-.markdown-body>*:last-child {
- margin-bottom: 0 !important;
-}
-
-.markdown-body a:not([href]) {
- color: inherit;
- text-decoration: none;
-}
-
-.markdown-body .anchor {
- position: absolute;
- top: 0;
- left: 0;
- display: block;
- padding-right: 6px;
- padding-left: 30px;
- margin-left: -30px;
-}
-
-.markdown-body .anchor:focus {
- outline: none;
-}
-
-.markdown-body h1,
-.markdown-body h2,
-.markdown-body h3,
-.markdown-body h4,
-.markdown-body h5,
-.markdown-body h6 {
- position: relative;
- margin-top: 1em;
- margin-bottom: 16px;
- font-weight: bold;
- line-height: 1.4;
-}
-
-.markdown-body h1 .octicon-link,
-.markdown-body h2 .octicon-link,
-.markdown-body h3 .octicon-link,
-.markdown-body h4 .octicon-link,
-.markdown-body h5 .octicon-link,
-.markdown-body h6 .octicon-link {
- display: none;
- color: #000;
- vertical-align: middle;
-}
-
-.markdown-body h1:hover .anchor,
-.markdown-body h2:hover .anchor,
-.markdown-body h3:hover .anchor,
-.markdown-body h4:hover .anchor,
-.markdown-body h5:hover .anchor,
-.markdown-body h6:hover .anchor {
- padding-left: 8px;
- margin-left: -30px;
- text-decoration: none;
-}
-
-.markdown-body h1:hover .anchor .octicon-link,
-.markdown-body h2:hover .anchor .octicon-link,
-.markdown-body h3:hover .anchor .octicon-link,
-.markdown-body h4:hover .anchor .octicon-link,
-.markdown-body h5:hover .anchor .octicon-link,
-.markdown-body h6:hover .anchor .octicon-link {
- display: inline-block;
-}
-
-.markdown-body h1 {
- padding-bottom: 0.3em;
- font-size: 2.25em;
- line-height: 1.2;
- border-bottom: 1px solid #eee;
-}
-
-.markdown-body h1 .anchor {
- line-height: 1;
-}
-
-.markdown-body h2 {
- padding-bottom: 0.3em;
- font-size: 1.75em;
- line-height: 1.225;
- border-bottom: 1px solid #eee;
-}
-
-.markdown-body h2 .anchor {
- line-height: 1;
-}
-
-.markdown-body h3 {
- font-size: 1.5em;
- line-height: 1.43;
-}
-
-.markdown-body h3 .anchor {
- line-height: 1.2;
-}
-
-.markdown-body h4 {
- font-size: 1.25em;
-}
-
-.markdown-body h4 .anchor {
- line-height: 1.2;
-}
-
-.markdown-body h5 {
- font-size: 1em;
-}
-
-.markdown-body h5 .anchor {
- line-height: 1.1;
-}
-
-.markdown-body h6 {
- font-size: 1em;
- color: #777;
-}
-
-.markdown-body h6 .anchor {
- line-height: 1.1;
-}
-
-.markdown-body p,
-.markdown-body blockquote,
-.markdown-body ul,
-.markdown-body ol,
-.markdown-body dl,
-.markdown-body table,
-.markdown-body pre {
- margin-top: 0;
- margin-bottom: 16px;
-}
-
-.markdown-body hr {
- height: 4px;
- padding: 0;
- margin: 16px 0;
- background-color: #e7e7e7;
- border: 0 none;
-}
-
-.markdown-body ul,
-.markdown-body ol {
- padding-left: 2em;
-}
-
-.markdown-body ul ul,
-.markdown-body ul ol,
-.markdown-body ol ol,
-.markdown-body ol ul {
- margin-top: 0;
- margin-bottom: 0;
-}
-
-.markdown-body li>p {
- margin-top: 16px;
-}
-
-.markdown-body dl {
- padding: 0;
-}
-
-.markdown-body dl dt {
- padding: 0;
- margin-top: 16px;
- font-size: 1em;
- font-style: italic;
- font-weight: bold;
-}
-
-.markdown-body dl dd {
- padding: 0 16px;
- margin-bottom: 16px;
-}
-
-.markdown-body blockquote {
- padding: 0 15px;
- color: #777;
- border-left: 4px solid #ddd;
-}
-
-.markdown-body blockquote>:first-child {
- margin-top: 0;
-}
-
-.markdown-body blockquote>:last-child {
- margin-bottom: 0;
-}
-
-.markdown-body table {
- display: block;
- width: 100%;
- overflow: auto;
- word-break: normal;
- word-break: keep-all;
-}
-
-.markdown-body table th {
- font-weight: bold;
-}
-
-.markdown-body table th,
-.markdown-body table td {
- padding: 6px 13px;
- border: 1px solid #ddd;
-}
-
-.markdown-body table tr {
- background-color: #fff;
- border-top: 1px solid #ccc;
-}
-
-.markdown-body table tr:nth-child(2n) {
- background-color: #f8f8f8;
-}
-
-.markdown-body img {
- max-width: 100%;
- box-sizing: border-box;
-}
-
-.markdown-body code {
- padding: 0;
- padding-top: 0.2em;
- padding-bottom: 0.2em;
- margin: 0;
- font-size: 85%;
- background-color: rgba(0,0,0,0.04);
- border-radius: 3px;
-}
-
-.markdown-body code:before,
-.markdown-body code:after {
- letter-spacing: -0.2em;
- content: "\00a0";
-}
-
-.markdown-body pre>code {
- padding: 0;
- margin: 0;
- font-size: 100%;
- word-break: normal;
- white-space: pre;
- background: transparent;
- border: 0;
-}
-
-.markdown-body .highlight {
- margin-bottom: 16px;
-}
-
-.markdown-body .highlight pre,
-.markdown-body pre {
- padding: 16px;
- overflow: auto;
- font-size: 85%;
- line-height: 1.45;
- background-color: #f7f7f7;
- border-radius: 3px;
-}
-
-.markdown-body .highlight pre {
- margin-bottom: 0;
- word-break: normal;
-}
-
-.markdown-body pre {
- word-wrap: normal;
-}
-
-.markdown-body pre code {
- display: inline;
- max-width: initial;
- padding: 0;
- margin: 0;
- overflow: initial;
- line-height: inherit;
- word-wrap: normal;
- background-color: transparent;
- border: 0;
-}
-
-.markdown-body pre code:before,
-.markdown-body pre code:after {
- content: normal;
-}
-
-.markdown-body kbd {
- display: inline-block;
- padding: 3px 5px;
- font-size: 11px;
- line-height: 10px;
- color: #555;
- vertical-align: middle;
- background-color: #fcfcfc;
- border: solid 1px #ccc;
- border-bottom-color: #bbb;
- border-radius: 3px;
- box-shadow: inset 0 -1px 0 #bbb;
-}
-
-.markdown-body .pl-c {
- color: #969896;
-}
-
-.markdown-body .pl-c1,
-.markdown-body .pl-s .pl-v {
- color: #0086b3;
-}
-
-.markdown-body .pl-e,
-.markdown-body .pl-en {
- color: #795da3;
-}
-
-.markdown-body .pl-s .pl-s1,
-.markdown-body .pl-smi {
- color: #333;
-}
-
-.markdown-body .pl-ent {
- color: #63a35c;
-}
-
-.markdown-body .pl-k {
- color: #a71d5d;
-}
-
-.markdown-body .pl-pds,
-.markdown-body .pl-s,
-.markdown-body .pl-s .pl-pse .pl-s1,
-.markdown-body .pl-sr,
-.markdown-body .pl-sr .pl-cce,
-.markdown-body .pl-sr .pl-sra,
-.markdown-body .pl-sr .pl-sre {
- color: #183691;
-}
-
-.markdown-body .pl-v {
- color: #ed6a43;
-}
-
-.markdown-body .pl-id {
- color: #b52a1d;
-}
-
-.markdown-body .pl-ii {
- background-color: #b52a1d;
- color: #f8f8f8;
-}
-
-.markdown-body .pl-sr .pl-cce {
- color: #63a35c;
- font-weight: bold;
-}
-
-.markdown-body .pl-ml {
- color: #693a17;
-}
-
-.markdown-body .pl-mh,
-.markdown-body .pl-mh .pl-en,
-.markdown-body .pl-ms {
- color: #1d3e81;
- font-weight: bold;
-}
-
-.markdown-body .pl-mq {
- color: #008080;
-}
-
-.markdown-body .pl-mi {
- color: #333;
- font-style: italic;
-}
-
-.markdown-body .pl-mb {
- color: #333;
- font-weight: bold;
-}
-
-.markdown-body .pl-md {
- background-color: #ffecec;
- color: #bd2c00;
-}
-
-.markdown-body .pl-mi1 {
- background-color: #eaffea;
- color: #55a532;
-}
-
-.markdown-body .pl-mdr {
- color: #795da3;
- font-weight: bold;
-}
-
-.markdown-body .pl-mo {
- color: #1d3e81;
-}
-
-.markdown-body kbd {
- display: inline-block;
- padding: 3px 5px;
- font: 11px Consolas, "Liberation Mono", Menlo, Courier, monospace;
- line-height: 10px;
- color: #555;
- vertical-align: middle;
- background-color: #fcfcfc;
- border: solid 1px #ccc;
- border-bottom-color: #bbb;
- border-radius: 3px;
- box-shadow: inset 0 -1px 0 #bbb;
-}
-
-.markdown-body .task-list-item {
- list-style-type: none;
-}
-
-.markdown-body .task-list-item+.task-list-item {
- margin-top: 3px;
-}
-
-.markdown-body .task-list-item input {
- margin: 0 0.35em 0.25em -1.6em;
- vertical-align: middle;
-}
-
-.markdown-body :checked+.radio-label {
- z-index: 1;
- position: relative;
- border-color: #4078c0;
-}
diff --git a/js/vendor/github-markdown-css/license b/js/vendor/github-markdown-css/license
deleted file mode 100644
index 654d0bfe..00000000
--- a/js/vendor/github-markdown-css/license
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/js/vendor/github-markdown-css/readme.md b/js/vendor/github-markdown-css/readme.md
deleted file mode 100644
index a58fe348..00000000
--- a/js/vendor/github-markdown-css/readme.md
+++ /dev/null
@@ -1,56 +0,0 @@
-# github-markdown-css
-
-> The minimal amount of CSS to replicate the GitHub Markdown style
-
-[<img src="https://cloud.githubusercontent.com/assets/170270/5219062/f22a978c-7685-11e4-8316-af25b6c89bc0.png" width="300">](http://sindresorhus.com/github-markdown-css)
-
-## [Demo](http://sindresorhus.com/github-markdown-css)
-
-
-## Install
-
-Download [manually](https://raw.githubusercontent.com/sindresorhus/github-markdown-css/gh-pages/github-markdown.css) or with a package-manager.
-
-```sh
-$ npm install --save github-markdown-css
-```
-
-```sh
-$ bower install --save github-markdown-css
-```
-
-
-## Usage
-
-Import the `github-markdown.css` file and add a `markdown-body` class to the container of your rendered Markdown and set a width for it. GitHub uses `790px` width and `30px` padding.
-
-```html
-<link rel="stylesheet" href="github-markdown.css">
-<style>
- .markdown-body {
- min-width: 200px;
- max-width: 790px;
- margin: 0 auto;
- padding: 30px;
- }
-</style>
-<article class="markdown-body">
- <h1>Unicorns</h1>
- <p>All the things</p>
-</article>
-```
-
-
-## How
-
-See [`generate-github-markdown-css`](https://github.com/sindresorhus/generate-github-markdown-css) for how it's generated and ability to generate your own.
-
-
-## Dev
-
-Run `npm run generate` to update the CSS.
-
-
-## License
-
-MIT © [Sindre Sorhus](http://sindresorhus.com)
diff --git a/js/vendor/image-scale/LICENSE b/js/vendor/image-scale/LICENSE
deleted file mode 100644
index b3908ae8..00000000
--- a/js/vendor/image-scale/LICENSE
+++ /dev/null
@@ -1,20 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2013 GestiXi
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software is furnished to do so,
-subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
-FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
-COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/js/vendor/image-scale/README.md b/js/vendor/image-scale/README.md
deleted file mode 100644
index 304ab691..00000000
--- a/js/vendor/image-scale/README.md
+++ /dev/null
@@ -1,210 +0,0 @@
-Image Scale
-===========
-
-**Scale images to fit or fill any target container via two simple properties: scale and align.**
-
-*This plugin is greatly inspired from Sproutcore SC.ImageView.*
-
-------
-
-## Installation
-
-image-scale depends on jQuery. To use it, include this in your page :
-
- <script src="jquery.js" type="text/javascript"></script>
- <script src="image-scale.js" type="text/javascript"></script>
-
-------
-
-## Usage
-
-If you want to identify the images that you want to scale, you can add a class to them. In this example we are adding a class call `scale`.
-
-You can also set the `data-scale` and `data-align` attributes directly to the images if you want to override the default setting.
-
- <div class="image-container">
- <img class="scale" data-scale="best-fit-down" data-align="center" src="img/example.jpg">
- </div>
-
-Now add this JavaScript code to your page :
-
- $(function() {
- $("img.scale").imageScale();
- });
-
-You're done.
-
-------
-
-## Properties
-
-
-### scale
-
-Determines how the image will scale to fit within its containing space. Possible values:
-
-* **fill** - stretches or compresses the source image to fill the target frame
-* **best-fill** - fits the shortest side of the source image within the target frame while maintaining the original aspect ratio
-* **best-fit** - fits the longest edge of the source image within the target frame while maintaining the original aspect ratio
-* **best-fit-down** - same as *best-fit* but will not stretch the source if it is smaller than the target
-* **none** - the source image is left unscaled
-
-<!-- -->
-
- Type: String
- Default: best-fill
-
-
-### align
-
-Align the image within its frame. Possible values:
-
-* **left**
-* **right**
-* **center**
-* **top**
-* **bottom**
-* **top-left**
-* **top-right**
-* **bottom-left**
-* **bottom-right**
-
-<!-- -->
-
- Type: String
- Default: center
-
-
-### parent
-
-A jQuery Object against which the image size will be calculated.
-If null, the parent of the image will be used.
-
- Type: jQuery Object
- Default: null
-
-
-### hideParentOverflow
-
-A boolean determining if the parent should hide its overflow.
-
- Type: Boolean
- Default: true
-
-
-### fadeInDuration
-
-A duration in milliseconds determining how long the fadeIn animation
-will run when your image is scale for the firstTime.
-
-Set it to 0 if you don't want any animation.
-
- Type: Number or String
- Default: 0
-
-
-### rescaleOnResize
-
-A boolean indicating if the image size should be rescaled when the window is resized.
-
-The window size is checked using requestAnimationFrame for good performance.
-
- Type: Boolean
- Default: false
-
-
-### didScale
-
-A function that will be call each time the receiver is scaled.
-
-Example:
-
- $images.imageScale({
- didScale: function(firstTime, options) {
- console.log('did scale img: ', this.element);
- }
- });
-
-<!-- -->
-
- Type: Function
- Parameters:
- - firstTime {Boolean} true if the image was scale for the first time.
- - options {Object} the options passed to the scale method.
-
-
-### debug
-
-A number indicating the debug level :
-
-0. silent
-1. error
-2. error & warning
-3. error & warning & notice
-
-<!-- -->
-
- Type: Number
- Default: 0
-
-------
-
-## Methods
-
-
-### scale
-
-Main method. Used to scale the images.
-
-When `rescaleOnResize` is set to true, this method is executed each time the
-windows size changes.
-
-If `rescaleOnResize` is set to false, you may want to call it manually. Here is an
-example on how you should do it:
-
- $image.imageScale('scale');
-
-
-### destroy
-
-Removes the data for the element.
-
-Here is an example on how you can call the destroy method:
-
- $image.imageScale('destroy');
-
-
-------
-
-## Demo
-
-See it in action on our [home page](https://www.gestixi.com).
-
-
-You can also check out the Sproutcore [Automatic Image Scaling demo](http://showcase.sproutcore.com/#demos/Automatic%20Image%20Scaling) to understand the difference between all the different options.
-
-
-------
-
-## Size
-
-Original Size: 3.91KB gzipped (13.99KB uncompressed)
-
-Compiled Size: **1.8KB gzipped** (4.42KB uncompressed)
-
-
-------
-
-## Author
-
-**Nicolas Badia**
-
-+ [https://twitter.com/@nicolas_badia](https://twitter.com/@nicolas_badia)
-+ [https://github.com/nicolasbadia](https://github.com/nicolasbadia)
-
-
-------
-
-## Copyright and license
-
-Copyright 2013-2015 GestiXi under [The MIT License (MIT)](LICENSE). \ No newline at end of file
diff --git a/js/vendor/image-scale/image-scale.js b/js/vendor/image-scale/image-scale.js
deleted file mode 100644
index 3934d35c..00000000
--- a/js/vendor/image-scale/image-scale.js
+++ /dev/null
@@ -1,512 +0,0 @@
-// ==========================================================================
-// Project: Image Scale
-// Description: Scale images to fit or fill any target size via two simple properties: scale and align.
-// Copyright: ©2012-2015 GestiXi
-// License: Licensed under the MIT license (see LICENCE)
-// Version: 2.1
-// Author: Nicolas BADIA
-// ==========================================================================
-
-! function($) {
- "use strict";
-
- // ..........................................................
- // IMAGE SCALE PLUGIN DEFINITION
- //
-
- $.fn.imageScale = function(options) {
-
- return this.each(function() {
- var that = this,
- $this = $(this),
- data = $this.data('imageScale'),
- $img = this.tagName === 'IMG' ? $this : $this.find("img");
-
- if (!data) {
- var didLoad = $img[0].complete,
- formattedOpt = $.extend({}, $.fn.imageScale.defaults, typeof options == 'object' && options),
-
- loadFunc = function() {
- $this.data('imageScale', (data = new ImageScale(that, formattedOpt)));
-
- data.scale(true, formattedOpt);
- };
-
- if (didLoad) {
- loadFunc.apply($this[0]);
- } else {
- $img.on("load", loadFunc).attr("src", $img.attr("src"));
- }
- } else {
- if (typeof options == 'string') data[options]();
- else if (typeof options == 'object') {
- var method = options.method || 'scale';
- data[method](false, options);
- } else data.scale();
- }
- })
- }
-
- $.fn.imageScale.defaults = {
- /**
- Determines how the image will scale to fit within its containing space. Possible values:
-
- * **fill** - stretches or compresses the source image to fill the target frame
- * **best-fill** - fits the shortest side of the source image within the target frame while maintaining the original aspect ratio
- * **best-fit** - fits the longest edge of the source image within the target frame while maintaining the original aspect ratio
- * **best-fit-down** - same as *best-fit* but will not stretch the source if it is smaller than the target
- * **none** - the source image is left unscaled
-
- @type String
- @default best-fill
- @since Version 1.2
- */
- scale: 'best-fill',
-
- /**
- Align the image within its frame. Possible values:
-
- * **left**
- * **right**
- * **center**
- * **top**
- * **bottom**
- * **top-left**
- * **top-right**
- * **bottom-left**
- * **bottom-right**
-
- @type String
- @default center
- @since Version 1.2
- */
- align: 'center',
-
- /**
- A jQuery Object against which the image size will be calculated.
- If null, the parent of the image will be used.
-
- @type jQuery Object
- @default null
- @since Version 1.0
- */
- parent: null,
-
- /**
- A boolean determining if the parent should hide its overflow.
-
- @type Boolean
- @default true
- @since Version 1.0
- */
- hideParentOverflow: true,
-
- /**
- A duration in milliseconds determining how long the fadeIn animation will run when your image is scale for the firstTime.
-
- Set it to 0 if you don't want any animation.
-
- @type Number|String
- @default 0
- @since Version 1.1
- */
- fadeInDuration: 0,
-
- /**
- A boolean indicating if the image size should be rescaled when the window is resized.
-
- The window size is checked using requestAnimationFrame for good performance.
-
- @type Boolean
- @default false
- @since Version 1.0
- */
- rescaleOnResize: false,
-
- /**
- A function that will be call each time the receiver is scaled.
-
- Example:
-
- $images.imageScale({
- didScale: function() {
- console.log('did scale img: ', this.element);
- }
- });
-
- @type Function
- @param firstTime {Boolean} true if the image was scale for the first time.
- @param options {Object} the options passed to the scale method.
- @since Version 2.0
- */
- didScale: function(firstTime, options) {},
-
- /**
- A number indicating the log level :
-
- 0: silent
- 1: error
- 2: error & warning
- 3: error & warning & notice
-
- @type Number
- @default 0
- @since Version 1.0
- */
- logLevel: 0
- }
-
- // ..........................................................
- // IMAGE SCALE PUBLIC CLASS DEFINITION
- //
-
- var ImageScale = function(element, options) {
- var that = this;
- that.options = options;
- that.element = element;
-
- var $element = that.$element = $(element),
- $img = that.$img = element.tagName === 'IMG' ? $element : $element.find("img"),
- img = that.img = $img[0];
-
- that.src = $img.attr('src');
-
- that.imgWidth = img.naturalWidth || img.width;
- that.imgHeight = img.naturalHeight || img.height;
-
- var $parent = that.$parent = options.parent ? options.parent : $($element.parent()[0]);
- that.parent = $parent[0];
-
- // Fixes: https://github.com/gestixi/image-scale/issues/1
- if ($parent.css('position') === 'static') {
- $parent.css('position', 'relative');
- }
-
- if (options.rescaleOnResize) {
- $(window).resize(function(e) {
- that.scheduleScale();
- });
- }
- }
-
- $.fn.imageScale.Constructor = ImageScale;
-
- ImageScale.prototype = {
-
- NONE: "none",
- FILL: "fill",
- BEST_FILL: "best-fill",
- BEST_FIT: "best-fit",
- BEST_FIT_DOWN_ONLY: "best-fit-down",
-
- ALIGN_LEFT: 'left',
- ALIGN_RIGHT: 'right',
- ALIGN_CENTER: 'center',
- ALIGN_TOP: 'top',
- ALIGN_BOTTOM: 'bottom',
- ALIGN_TOP_LEFT: 'top-left',
- ALIGN_TOP_RIGHT: 'top-right',
- ALIGN_BOTTOM_LEFT: 'bottom-left',
- ALIGN_BOTTOM_RIGHT: 'bottom-right',
-
- constructor: ImageScale,
-
- /**
- The initial element.
-
- @type DOM Element
- */
- element: null,
-
- /**
- The passed options.
-
- @type Object
- */
- options: null,
-
- /**
- Main method. Used to scale the images.
-
- When `rescaleOnResize` is set to true, this method is executed each time the
- windows size changes.
-
- If `rescaleOnResize` is set to false, you may want to call it manually. Here is an
- example on how you should do it:
-
- $image.imageScale('scale');
-
-
- @param {Boolean} firstTime
- */
- scale: function(firstTime, opt) {
- if (this._isDestroyed || this._canScale === false) return;
-
- var that = this,
- options = this.options,
- $parent = this.$parent,
- element = this.element,
- $element = this.$element,
- img = this.img,
- $img = this.$img;
-
- if (firstTime) {
- if (options.hideParentOverflow) {
- $parent.css({
- overflow: 'hidden'
- });
- }
- } else {
- // If the source of the image has changed
- if (this.src !== $img.attr('src')) {
- this.destroy();
- $element.data('imageScale', null);
- $element.imageScale(options);
- return;
- }
- }
-
- this._didScheduleScale = false;
-
- if (options.rescaleOnResize && !opt) {
- if (!this._needUpdate(this.parent)) return;
- }
- opt = opt ? opt : {};
-
- var transition = opt.transition;
- if (transition) {
- this._canScale = false;
- $element.css('transition', 'all ' + transition + 'ms');
-
- setTimeout(function() {
- that._canScale = null;
- $element.css('transition', 'null');
- }, transition);
- }
-
- var destWidth = opt.destWidth ? opt.destWidth : $parent.outerWidth(),
- destHeight = opt.destHeight ? opt.destHeight : $parent.outerHeight(),
-
- destInnerWidth = opt.destWidth ? opt.destWidth : $parent.innerWidth(),
- destInnerHeight = opt.destHeight ? opt.destHeight : $parent.innerHeight(),
-
- widthOffset = destWidth - destInnerWidth,
- heightOffset = destHeight - destInnerHeight,
-
- scaleData = $element.attr('data-scale'),
- alignData = $element.attr('data-align'),
-
- scale = scaleData ? scaleData : options.scale,
- align = alignData ? alignData : options.align,
-
- fadeInDuration = options.fadeInDuration;
-
- if (!scale) {
- if (options.logLevel > 2) {
- console.log("imageScale - DEBUG NOTICE: The scale property is null.", element);
- }
- return;
- }
-
- if (this._cacheDestWidth === destWidth && this._cacheDestHeight === destHeight) {
- if (options.logLevel > 2) {
- console.log("imageScale - DEBUG NOTICE: The parent size hasn't changed: dest width: '" + destWidth + "' - dest height: '" + destHeight + "'.", element);
- }
- }
-
- var sourceWidth = this.imgWidth,
- sourceHeight = this.imgHeight;
-
- if (!(destWidth && destHeight && sourceWidth && sourceHeight)) {
- if (options.logLevel > 0) {
- console.error("imageScale - DEBUG ERROR: The dimensions are incorrect: source width: '" + sourceWidth + "' - source height: '" + sourceHeight + "' - dest width: '" + destWidth + "' - dest height: '" + destHeight + "'.", element);
- }
- return;
- }
-
- this._cacheDestWidth = destWidth;
- this._cacheDestHeight = destHeight;
-
- var layout = this._innerFrameForSize(scale, align, sourceWidth, sourceHeight, destWidth, destHeight);
-
- if (widthOffset) layout.x -= widthOffset / 2;
- if (heightOffset) layout.y -= heightOffset / 2;
-
- $element.css({
- position: 'absolute',
- top: layout.y + 'px',
- left: layout.x + 'px',
- width: layout.width + 'px',
- height: layout.height + 'px',
- 'max-width': 'none'
- });
-
- if (firstTime && fadeInDuration) {
- $element.css({
- display: 'none'
- });
- $element.fadeIn(fadeInDuration);
- }
-
- options.didScale.call(this, firstTime, opt);
- },
-
- /**
- Removes the data for the element.
-
- Here is an example on how you can call the destroy method:
-
- $image.imageScale('destroy');
-
- */
- destroy: function() {
- this._isDestroyed = true;
- this.$element.removeData('imageScale');
- },
-
- /**
- @private
-
- Returns a frame (x, y, width, height) fitting the source size (sourceWidth & sourceHeight) within the
- destination size (destWidth & destHeight) according to the align and scale properties.
-
- @param {String} scale
- @param {String} align
- @param {Number} sourceWidth
- @param {Number} sourceHeight
- @param {Number} destWidth
- @param {Number} destHeight
- @returns {Object} the inner frame with properties: { x: value, y: value, width: value, height: value }
- */
- _innerFrameForSize: function(scale, align, sourceWidth, sourceHeight, destWidth, destHeight) {
- var scaleX,
- scaleY,
- result;
-
- // Fast path
- result = {
- x: 0,
- y: 0,
- width: destWidth,
- height: destHeight
- };
- if (scale === this.FILL) return result;
-
- // Determine the appropriate scale
- scaleX = destWidth / sourceWidth;
- scaleY = destHeight / sourceHeight;
-
- switch (scale) {
- case this.BEST_FIT_DOWN_ONLY:
- if (scale !== this.BEST_FIT_DOWN_ONLY && this.options.logLevel > 1) {
- console.warn("imageScale - DEBUG WARNING: The scale '" + scale + "' was not understood.");
- }
-
- if ((sourceWidth > destWidth) || (sourceHeight > destHeight)) {
- scale = scaleX < scaleY ? scaleX : scaleY;
- } else {
- scale = 1.0;
- }
- break;
- case this.BEST_FIT:
- scale = scaleX < scaleY ? scaleX : scaleY;
- break;
- case this.NONE:
- scale = 1.0;
- break;
- //case this.BEST_FILL:
- default:
- scale = scaleX > scaleY ? scaleX : scaleY;
- break;
- }
-
- sourceWidth *= scale;
- sourceHeight *= scale;
- result.width = Math.round(sourceWidth);
- result.height = Math.round(sourceHeight);
-
- // Align the image within its frame
- switch (align) {
- case this.ALIGN_LEFT:
- result.x = 0;
- result.y = (destHeight / 2) - (sourceHeight / 2);
- break;
- case this.ALIGN_RIGHT:
- result.x = destWidth - sourceWidth;
- result.y = (destHeight / 2) - (sourceHeight / 2);
- break;
- case this.ALIGN_TOP:
- result.x = (destWidth / 2) - (sourceWidth / 2);
- result.y = 0;
- break;
- case this.ALIGN_BOTTOM:
- result.x = (destWidth / 2) - (sourceWidth / 2);
- result.y = destHeight - sourceHeight;
- break;
- case this.ALIGN_TOP_LEFT:
- result.x = 0;
- result.y = 0;
- break;
- case this.ALIGN_TOP_RIGHT:
- result.x = destWidth - sourceWidth;
- result.y = 0;
- break;
- case this.ALIGN_BOTTOM_LEFT:
- result.x = 0;
- result.y = destHeight - sourceHeight;
- break;
- case this.ALIGN_BOTTOM_RIGHT:
- result.x = destWidth - sourceWidth;
- result.y = destHeight - sourceHeight;
- break;
- default: // this.ALIGN_CENTER
- if (align !== this.ALIGN_CENTER && this.options.logLevel > 1) {
- console.warn("imageScale - DEBUG WARNING: The align '" + align + "' was not understood.");
- }
- result.x = (destWidth / 2) - (sourceWidth / 2);
- result.y = (destHeight / 2) - (sourceHeight / 2);
- }
-
- return result;
- },
-
- /**
- @private
-
- Determines if the windows size has changed since the last update.
-
- @returns {Boolean}
- */
- _needUpdate: function(parent) {
- var size = parent.clientHeight + ' ' + parent.clientWidth;
-
- if (this._lastParentSize !== size) {
- this._lastParentSize = size;
- return true;
- }
- return false;
- },
-
- /**
- @private
-
- Schedule a scale update.
- */
- scheduleScale: function() {
- if (this._didScheduleScale) return;
-
- if (window.requestAnimationFrame) {
- var that = this;
- this._didScheduleScale = true;
- // setTimeout important when resizing down if the scrollbar were visible
- requestAnimationFrame(function() {
- setTimeout(function() {
- that.scale();
- }, 0);
- });
- } else {
- this.scale();
- }
- }
- }
-}(window.jQuery); \ No newline at end of file
diff --git a/js/vendor/marked/.bower.json b/js/vendor/marked/.bower.json
deleted file mode 100644
index dc9c1bb0..00000000
--- a/js/vendor/marked/.bower.json
+++ /dev/null
@@ -1,33 +0,0 @@
-{
- "name": "marked",
- "version": "0.3.3",
- "homepage": "https://github.com/chjj/marked",
- "authors": [
- "Christopher Jeffrey <chjjeffrey@gmail.com>"
- ],
- "description": "A markdown parser built for speed",
- "keywords": [
- "markdown",
- "markup",
- "html"
- ],
- "main": "lib/marked.js",
- "license": "MIT",
- "ignore": [
- "**/.*",
- "node_modules",
- "bower_components",
- "app/bower_components",
- "test",
- "tests"
- ],
- "_release": "0.3.3",
- "_resolution": {
- "type": "version",
- "tag": "v0.3.3",
- "commit": "2b5802f258c5e23e48366f2377fbb4c807f47658"
- },
- "_source": "git://github.com/chjj/marked.git",
- "_target": "~0.*",
- "_originalSource": "marked"
-} \ No newline at end of file
diff --git a/js/vendor/marked/LICENSE b/js/vendor/marked/LICENSE
deleted file mode 100644
index a7b812ed..00000000
--- a/js/vendor/marked/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2011-2014, Christopher Jeffrey (https://github.com/chjj/)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/js/vendor/marked/Makefile b/js/vendor/marked/Makefile
deleted file mode 100644
index d9349f07..00000000
--- a/js/vendor/marked/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-all:
- @cp lib/marked.js marked.js
- @uglifyjs --comments '/\*[^\0]+?Copyright[^\0]+?\*/' -o marked.min.js lib/marked.js
-
-clean:
- @rm marked.js
- @rm marked.min.js
-
-bench:
- @node test --bench
-
-.PHONY: clean all
diff --git a/js/vendor/marked/README.md b/js/vendor/marked/README.md
deleted file mode 100644
index b9817cd4..00000000
--- a/js/vendor/marked/README.md
+++ /dev/null
@@ -1,406 +0,0 @@
-# marked
-
-> A full-featured markdown parser and compiler, written in JavaScript. Built
-> for speed.
-
-[![NPM version](https://badge.fury.io/js/marked.png)][badge]
-
-## Install
-
-``` bash
-npm install marked --save
-```
-
-## Usage
-
-Minimal usage:
-
-```js
-var marked = require('marked');
-console.log(marked('I am using __markdown__.'));
-// Outputs: <p>I am using <strong>markdown</strong>.</p>
-```
-
-Example setting options with default values:
-
-```js
-var marked = require('marked');
-marked.setOptions({
- renderer: new marked.Renderer(),
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: true,
- smartLists: true,
- smartypants: false
-});
-
-console.log(marked('I am using __markdown__.'));
-```
-
-### Browser
-
-```html
-<!doctype html>
-<html>
-<head>
- <meta charset="utf-8"/>
- <title>Marked in the browser</title>
- <script src="lib/marked.js"></script>
-</head>
-<body>
- <div id="content"></div>
- <script>
- document.getElementById('content').innerHTML =
- marked('# Marked in browser\n\nRendered by **marked**.');
- </script>
-</body>
-</html>
-```
-
-## marked(markdownString [,options] [,callback])
-
-### markdownString
-
-Type: `string`
-
-String of markdown source to be compiled.
-
-### options
-
-Type: `object`
-
-Hash of options. Can also be set using the `marked.setOptions` method as seen
-above.
-
-### callback
-
-Type: `function`
-
-Function called when the `markdownString` has been fully parsed when using
-async highlighting. If the `options` argument is omitted, this can be used as
-the second argument.
-
-## Options
-
-### highlight
-
-Type: `function`
-
-A function to highlight code blocks. The first example below uses async highlighting with
-[node-pygmentize-bundled][pygmentize], and the second is a synchronous example using
-[highlight.js][highlight]:
-
-```js
-var marked = require('marked');
-
-var markdownString = '```js\n console.log("hello"); \n```';
-
-// Async highlighting with pygmentize-bundled
-marked.setOptions({
- highlight: function (code, lang, callback) {
- require('pygmentize-bundled')({ lang: lang, format: 'html' }, code, function (err, result) {
- callback(err, result.toString());
- });
- }
-});
-
-// Using async version of marked
-marked(markdownString, function (err, content) {
- if (err) throw err;
- console.log(content);
-});
-
-// Synchronous highlighting with highlight.js
-marked.setOptions({
- highlight: function (code) {
- return require('highlight.js').highlightAuto(code).value;
- }
-});
-
-console.log(marked(markdownString));
-```
-
-#### highlight arguments
-
-`code`
-
-Type: `string`
-
-The section of code to pass to the highlighter.
-
-`lang`
-
-Type: `string`
-
-The programming language specified in the code block.
-
-`callback`
-
-Type: `function`
-
-The callback function to call when using an async highlighter.
-
-### renderer
-
-Type: `object`
-Default: `new Renderer()`
-
-An object containing functions to render tokens to HTML.
-
-#### Overriding renderer methods
-
-The renderer option allows you to render tokens in a custom manor. Here is an
-example of overriding the default heading token rendering by adding an embedded anchor tag like on GitHub:
-
-```javascript
-var marked = require('marked');
-var renderer = new marked.Renderer();
-
-renderer.heading = function (text, level) {
- var escapedText = text.toLowerCase().replace(/[^\w]+/g, '-');
-
- return '<h' + level + '><a name="' +
- escapedText +
- '" class="anchor" href="#' +
- escapedText +
- '"><span class="header-link"></span></a>' +
- text + '</h' + level + '>';
-},
-
-console.log(marked('# heading+', { renderer: renderer }));
-```
-This code will output the following HTML:
-```html
-<h1>
- <a name="heading-" class="anchor" href="#heading-">
- <span class="header-link"></span>
- </a>
- heading+
-</h1>
-```
-
-#### Block level renderer methods
-
-- code(*string* code, *string* language)
-- blockquote(*string* quote)
-- html(*string* html)
-- heading(*string* text, *number* level)
-- hr()
-- list(*string* body, *boolean* ordered)
-- listitem(*string* text)
-- paragraph(*string* text)
-- table(*string* header, *string* body)
-- tablerow(*string* content)
-- tablecell(*string* content, *object* flags)
-
-`flags` has the following properties:
-
-```js
-{
- header: true || false,
- align: 'center' || 'left' || 'right'
-}
-```
-
-#### Inline level renderer methods
-
-- strong(*string* text)
-- em(*string* text)
-- codespan(*string* code)
-- br()
-- del(*string* text)
-- link(*string* href, *string* title, *string* text)
-- image(*string* href, *string* title, *string* text)
-
-### gfm
-
-Type: `boolean`
-Default: `true`
-
-Enable [GitHub flavored markdown][gfm].
-
-### tables
-
-Type: `boolean`
-Default: `true`
-
-Enable GFM [tables][tables].
-This option requires the `gfm` option to be true.
-
-### breaks
-
-Type: `boolean`
-Default: `false`
-
-Enable GFM [line breaks][breaks].
-This option requires the `gfm` option to be true.
-
-### pedantic
-
-Type: `boolean`
-Default: `false`
-
-Conform to obscure parts of `markdown.pl` as much as possible. Don't fix any of
-the original markdown bugs or poor behavior.
-
-### sanitize
-
-Type: `boolean`
-Default: `false`
-
-Sanitize the output. Ignore any HTML that has been input.
-
-### smartLists
-
-Type: `boolean`
-Default: `true`
-
-Use smarter list behavior than the original markdown. May eventually be
-default with the old behavior moved into `pedantic`.
-
-### smartypants
-
-Type: `boolean`
-Default: `false`
-
-Use "smart" typograhic punctuation for things like quotes and dashes.
-
-## Access to lexer and parser
-
-You also have direct access to the lexer and parser if you so desire.
-
-``` js
-var tokens = marked.lexer(text, options);
-console.log(marked.parser(tokens));
-```
-
-``` js
-var lexer = new marked.Lexer(options);
-var tokens = lexer.lex(text);
-console.log(tokens);
-console.log(lexer.rules);
-```
-
-## CLI
-
-``` bash
-$ marked -o hello.html
-hello world
-^D
-$ cat hello.html
-<p>hello world</p>
-```
-
-## Philosophy behind marked
-
-The point of marked was to create a markdown compiler where it was possible to
-frequently parse huge chunks of markdown without having to worry about
-caching the compiled output somehow...or blocking for an unnecesarily long time.
-
-marked is very concise and still implements all markdown features. It is also
-now fully compatible with the client-side.
-
-marked more or less passes the official markdown test suite in its
-entirety. This is important because a surprising number of markdown compilers
-cannot pass more than a few tests. It was very difficult to get marked as
-compliant as it is. It could have cut corners in several areas for the sake
-of performance, but did not in order to be exactly what you expect in terms
-of a markdown rendering. In fact, this is why marked could be considered at a
-disadvantage in the benchmarks above.
-
-Along with implementing every markdown feature, marked also implements [GFM
-features][gfmf].
-
-## Benchmarks
-
-node v0.8.x
-
-``` bash
-$ node test --bench
-marked completed in 3411ms.
-marked (gfm) completed in 3727ms.
-marked (pedantic) completed in 3201ms.
-robotskirt completed in 808ms.
-showdown (reuse converter) completed in 11954ms.
-showdown (new converter) completed in 17774ms.
-markdown-js completed in 17191ms.
-```
-
-__Marked is now faster than Discount, which is written in C.__
-
-For those feeling skeptical: These benchmarks run the entire markdown test suite 1000 times. The test suite tests every feature. It doesn't cater to specific aspects.
-
-### Pro level
-
-You also have direct access to the lexer and parser if you so desire.
-
-``` js
-var tokens = marked.lexer(text, options);
-console.log(marked.parser(tokens));
-```
-
-``` js
-var lexer = new marked.Lexer(options);
-var tokens = lexer.lex(text);
-console.log(tokens);
-console.log(lexer.rules);
-```
-
-``` bash
-$ node
-> require('marked').lexer('> i am using marked.')
-[ { type: 'blockquote_start' },
- { type: 'paragraph',
- text: 'i am using marked.' },
- { type: 'blockquote_end' },
- links: {} ]
-```
-
-## Running Tests & Contributing
-
-If you want to submit a pull request, make sure your changes pass the test
-suite. If you're adding a new feature, be sure to add your own test.
-
-The marked test suite is set up slightly strangely: `test/new` is for all tests
-that are not part of the original markdown.pl test suite (this is where your
-test should go if you make one). `test/original` is only for the original
-markdown.pl tests. `test/tests` houses both types of tests after they have been
-combined and moved/generated by running `node test --fix` or `marked --test
---fix`.
-
-In other words, if you have a test to add, add it to `test/new/` and then
-regenerate the tests with `node test --fix`. Commit the result. If your test
-uses a certain feature, for example, maybe it assumes GFM is *not* enabled, you
-can add `.nogfm` to the filename. So, `my-test.text` becomes
-`my-test.nogfm.text`. You can do this with any marked option. Say you want
-line breaks and smartypants enabled, your filename should be:
-`my-test.breaks.smartypants.text`.
-
-To run the tests:
-
-``` bash
-cd marked/
-node test
-```
-
-### Contribution and License Agreement
-
-If you contribute code to this project, you are implicitly allowing your code
-to be distributed under the MIT license. You are also implicitly verifying that
-all code is your original work. `</legalese>`
-
-## License
-
-Copyright (c) 2011-2014, Christopher Jeffrey. (MIT License)
-
-See LICENSE for more info.
-
-[gfm]: https://help.github.com/articles/github-flavored-markdown
-[gfmf]: http://github.github.com/github-flavored-markdown/
-[pygmentize]: https://github.com/rvagg/node-pygmentize-bundled
-[highlight]: https://github.com/isagalaev/highlight.js
-[badge]: http://badge.fury.io/js/marked
-[tables]: https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#wiki-tables
-[breaks]: https://help.github.com/articles/github-flavored-markdown#newlines
diff --git a/js/vendor/marked/bin/marked b/js/vendor/marked/bin/marked
deleted file mode 100644
index 64254fc3..00000000
--- a/js/vendor/marked/bin/marked
+++ /dev/null
@@ -1,187 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * Marked CLI
- * Copyright (c) 2011-2013, Christopher Jeffrey (MIT License)
- */
-
-var fs = require('fs')
- , util = require('util')
- , marked = require('../');
-
-/**
- * Man Page
- */
-
-function help() {
- var spawn = require('child_process').spawn;
-
- var options = {
- cwd: process.cwd(),
- env: process.env,
- setsid: false,
- customFds: [0, 1, 2]
- };
-
- spawn('man',
- [__dirname + '/../man/marked.1'],
- options);
-}
-
-/**
- * Main
- */
-
-function main(argv, callback) {
- var files = []
- , options = {}
- , input
- , output
- , arg
- , tokens
- , opt;
-
- function getarg() {
- var arg = argv.shift();
-
- if (arg.indexOf('--') === 0) {
- // e.g. --opt
- arg = arg.split('=');
- if (arg.length > 1) {
- // e.g. --opt=val
- argv.unshift(arg.slice(1).join('='));
- }
- arg = arg[0];
- } else if (arg[0] === '-') {
- if (arg.length > 2) {
- // e.g. -abc
- argv = arg.substring(1).split('').map(function(ch) {
- return '-' + ch;
- }).concat(argv);
- arg = argv.shift();
- } else {
- // e.g. -a
- }
- } else {
- // e.g. foo
- }
-
- return arg;
- }
-
- while (argv.length) {
- arg = getarg();
- switch (arg) {
- case '--test':
- return require('../test').main(process.argv.slice());
- case '-o':
- case '--output':
- output = argv.shift();
- break;
- case '-i':
- case '--input':
- input = argv.shift();
- break;
- case '-t':
- case '--tokens':
- tokens = true;
- break;
- case '-h':
- case '--help':
- return help();
- default:
- if (arg.indexOf('--') === 0) {
- opt = camelize(arg.replace(/^--(no-)?/, ''));
- if (!marked.defaults.hasOwnProperty(opt)) {
- continue;
- }
- if (arg.indexOf('--no-') === 0) {
- options[opt] = typeof marked.defaults[opt] !== 'boolean'
- ? null
- : false;
- } else {
- options[opt] = typeof marked.defaults[opt] !== 'boolean'
- ? argv.shift()
- : true;
- }
- } else {
- files.push(arg);
- }
- break;
- }
- }
-
- function getData(callback) {
- if (!input) {
- if (files.length <= 2) {
- return getStdin(callback);
- }
- input = files.pop();
- }
- return fs.readFile(input, 'utf8', callback);
- }
-
- return getData(function(err, data) {
- if (err) return callback(err);
-
- data = tokens
- ? JSON.stringify(marked.lexer(data, options), null, 2)
- : marked(data, options);
-
- if (!output) {
- process.stdout.write(data + '\n');
- return callback();
- }
-
- return fs.writeFile(output, data, callback);
- });
-}
-
-/**
- * Helpers
- */
-
-function getStdin(callback) {
- var stdin = process.stdin
- , buff = '';
-
- stdin.setEncoding('utf8');
-
- stdin.on('data', function(data) {
- buff += data;
- });
-
- stdin.on('error', function(err) {
- return callback(err);
- });
-
- stdin.on('end', function() {
- return callback(null, buff);
- });
-
- try {
- stdin.resume();
- } catch (e) {
- callback(e);
- }
-}
-
-function camelize(text) {
- return text.replace(/(\w)-(\w)/g, function(_, a, b) {
- return a + b.toUpperCase();
- });
-}
-
-/**
- * Expose / Entry Point
- */
-
-if (!module.parent) {
- process.title = 'marked';
- main(process.argv.slice(), function(err, code) {
- if (err) throw err;
- return process.exit(code || 0);
- });
-} else {
- module.exports = main;
-}
diff --git a/js/vendor/marked/bower.json b/js/vendor/marked/bower.json
deleted file mode 100644
index 3eab3110..00000000
--- a/js/vendor/marked/bower.json
+++ /dev/null
@@ -1,24 +0,0 @@
-{
- "name": "marked",
- "version": "0.3.2",
- "homepage": "https://github.com/chjj/marked",
- "authors": [
- "Christopher Jeffrey <chjjeffrey@gmail.com>"
- ],
- "description": "A markdown parser built for speed",
- "keywords": [
- "markdown",
- "markup",
- "html"
- ],
- "main": "lib/marked.js",
- "license": "MIT",
- "ignore": [
- "**/.*",
- "node_modules",
- "bower_components",
- "app/bower_components",
- "test",
- "tests"
- ]
-}
diff --git a/js/vendor/marked/component.json b/js/vendor/marked/component.json
deleted file mode 100644
index 931cbedc..00000000
--- a/js/vendor/marked/component.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "name": "marked",
- "version": "0.3.2",
- "repo": "chjj/marked",
- "description": "A markdown parser built for speed",
- "keywords": ["markdown", "markup", "html"],
- "scripts": ["lib/marked.js"],
- "main": "lib/marked.js",
- "license": "MIT"
-}
diff --git a/js/vendor/marked/doc/broken.md b/js/vendor/marked/doc/broken.md
deleted file mode 100644
index 7bfa49e8..00000000
--- a/js/vendor/marked/doc/broken.md
+++ /dev/null
@@ -1,426 +0,0 @@
-# Markdown is broken
-
-I have a lot of scraps of markdown engine oddities that I've collected over the
-years. What you see below is slightly messy, but it's what I've managed to
-cobble together to illustrate the differences between markdown engines, and
-why, if there ever is a markdown specification, it has to be absolutely
-thorough. There are a lot more of these little differences I have documented
-elsewhere. I know I will find them lingering on my disk one day, but until
-then, I'll continue to add whatever strange nonsensical things I find.
-
-Some of these examples may only mention a particular engine compared to marked.
-However, the examples with markdown.pl could easily be swapped out for
-discount, upskirt, or markdown.js, and you would very easily see even more
-inconsistencies.
-
-A lot of this was written when I was very unsatisfied with the inconsistencies
-between markdown engines. Please excuse the frustration noticeable in my
-writing.
-
-## Examples of markdown's "stupid" list parsing
-
-```
-$ markdown.pl
-
- * item1
-
- * item2
-
- text
-^D
-<ul>
-<li><p>item1</p>
-
-<ul>
-<li>item2</li>
-</ul>
-
-<p><p>text</p></li>
-</ul></p>
-```
-
-
-```
-$ marked
- * item1
-
- * item2
-
- text
-^D
-<ul>
-<li><p>item1</p>
-<ul>
-<li>item2</li>
-</ul>
-<p>text</p>
-</li>
-</ul>
-```
-
-Which looks correct to you?
-
-- - -
-
-```
-$ markdown.pl
-* hello
- > world
-^D
-<p><ul>
-<li>hello</p>
-
-<blockquote>
- <p>world</li>
-</ul></p>
-</blockquote>
-```
-
-```
-$ marked
-* hello
- > world
-^D
-<ul>
-<li>hello<blockquote>
-<p>world</p>
-</blockquote>
-</li>
-</ul>
-```
-
-Again, which looks correct to you?
-
-- - -
-
-EXAMPLE:
-
-```
-$ markdown.pl
-* hello
- * world
- * hi
- code
-^D
-<ul>
-<li>hello
-<ul>
-<li>world</li>
-<li>hi
- code</li>
-</ul></li>
-</ul>
-```
-
-The code isn't a code block even though it's after the bullet margin. I know,
-lets give it two more spaces, effectively making it 8 spaces past the bullet.
-
-```
-$ markdown.pl
-* hello
- * world
- * hi
- code
-^D
-<ul>
-<li>hello
-<ul>
-<li>world</li>
-<li>hi
- code</li>
-</ul></li>
-</ul>
-```
-
-And, it's still not a code block. Did you also notice that the 3rd item isn't
-even its own list? Markdown screws that up too because of its indentation
-unaware parsing.
-
-- - -
-
-Let's look at some more examples of markdown's list parsing:
-
-```
-$ markdown.pl
-
- * item1
-
- * item2
-
- text
-^D
-<ul>
-<li><p>item1</p>
-
-<ul>
-<li>item2</li>
-</ul>
-
-<p><p>text</p></li>
-</ul></p>
-```
-
-Misnested tags.
-
-
-```
-$ marked
- * item1
-
- * item2
-
- text
-^D
-<ul>
-<li><p>item1</p>
-<ul>
-<li>item2</li>
-</ul>
-<p>text</p>
-</li>
-</ul>
-```
-
-Which looks correct to you?
-
-- - -
-
-```
-$ markdown.pl
-* hello
- > world
-^D
-<p><ul>
-<li>hello</p>
-
-<blockquote>
- <p>world</li>
-</ul></p>
-</blockquote>
-```
-
-More misnested tags.
-
-
-```
-$ marked
-* hello
- > world
-^D
-<ul>
-<li>hello<blockquote>
-<p>world</p>
-</blockquote>
-</li>
-</ul>
-```
-
-Again, which looks correct to you?
-
-- - -
-
-# Why quality matters - Part 2
-
-``` bash
-$ markdown.pl
-* hello
- > world
-^D
-<p><ul>
-<li>hello</p>
-
-<blockquote>
- <p>world</li>
-</ul></p>
-</blockquote>
-```
-
-``` bash
-$ sundown # upskirt
-* hello
- > world
-^D
-<ul>
-<li>hello
-&gt; world</li>
-</ul>
-```
-
-``` bash
-$ marked
-* hello
- > world
-^D
-<ul><li>hello <blockquote><p>world</p></blockquote></li></ul>
-```
-
-Which looks correct to you?
-
-- - -
-
-See: https://github.com/evilstreak/markdown-js/issues/23
-
-``` bash
-$ markdown.pl # upskirt/markdown.js/discount
-* hello
- var a = 1;
-* world
-^D
-<ul>
-<li>hello
-var a = 1;</li>
-<li>world</li>
-</ul>
-```
-
-``` bash
-$ marked
-* hello
- var a = 1;
-* world
-^D
-<ul><li>hello
-<pre>code>var a = 1;</code></pre></li>
-<li>world</li></ul>
-```
-
-Which looks more reasonable? Why shouldn't code blocks be able to appear in
-list items in a sane way?
-
-- - -
-
-``` bash
-$ markdown.js
-<div>hello</div>
-
-<span>hello</span>
-^D
-<p>&lt;div&gt;hello&lt;/div&gt;</p>
-
-<p>&lt;span&gt;hello&lt;/span&gt;</p>
-```
-
-``` bash
-$ marked
-<div>hello</div>
-
-<span>hello</span>
-^D
-<div>hello</div>
-
-
-<p><span>hello</span>
-</p>
-```
-
-- - -
-
-See: https://github.com/evilstreak/markdown-js/issues/27
-
-``` bash
-$ markdown.js
-[![an image](/image)](/link)
-^D
-<p><a href="/image)](/link">![an image</a></p>
-```
-
-``` bash
-$ marked
-[![an image](/image)](/link)
-^D
-<p><a href="/link"><img src="/image" alt="an image"></a>
-</p>
-```
-
-- - -
-
-See: https://github.com/evilstreak/markdown-js/issues/24
-
-``` bash
-$ markdown.js
-> a
-
-> b
-
-> c
-^D
-<blockquote><p>a</p><p>bundefined&gt; c</p></blockquote>
-```
-
-``` bash
-$ marked
-> a
-
-> b
-
-> c
-^D
-<blockquote><p>a
-
-</p></blockquote>
-<blockquote><p>b
-
-</p></blockquote>
-<blockquote><p>c
-</p></blockquote>
-```
-
-- - -
-
-``` bash
-$ markdown.pl
-* hello
- * world
- how
-
- are
- you
-
- * today
-* hi
-^D
-<ul>
-<li><p>hello</p>
-
-<ul>
-<li>world
-how</li>
-</ul>
-
-<p>are
-you</p>
-
-<ul>
-<li>today</li>
-</ul></li>
-<li>hi</li>
-</ul>
-```
-
-``` bash
-$ marked
-* hello
- * world
- how
-
- are
- you
-
- * today
-* hi
-^D
-<ul>
-<li><p>hello</p>
-<ul>
-<li><p>world
-how</p>
-<p>are
-you</p>
-</li>
-<li><p>today</p>
-</li>
-</ul>
-</li>
-<li>hi</li>
-</ul>
-```
diff --git a/js/vendor/marked/doc/todo.md b/js/vendor/marked/doc/todo.md
deleted file mode 100644
index 2e60b162..00000000
--- a/js/vendor/marked/doc/todo.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Todo
-
diff --git a/js/vendor/marked/index.js b/js/vendor/marked/index.js
deleted file mode 100644
index a12f9056..00000000
--- a/js/vendor/marked/index.js
+++ /dev/null
@@ -1 +0,0 @@
-module.exports = require('./lib/marked');
diff --git a/js/vendor/marked/lib/marked.js b/js/vendor/marked/lib/marked.js
deleted file mode 100644
index 0b7180ff..00000000
--- a/js/vendor/marked/lib/marked.js
+++ /dev/null
@@ -1,1272 +0,0 @@
-/**
- * marked - a markdown parser
- * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
- * https://github.com/chjj/marked
- */
-
-;(function() {
-
-/**
- * Block-Level Grammar
- */
-
-var block = {
- newline: /^\n+/,
- code: /^( {4}[^\n]+\n*)+/,
- fences: noop,
- hr: /^( *[-*_]){3,} *(?:\n+|$)/,
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
- nptable: noop,
- lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
- blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
- list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
- html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
- table: noop,
- paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
- text: /^[^\n]+/
-};
-
-block.bullet = /(?:[*+-]|\d+\.)/;
-block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
-block.item = replace(block.item, 'gm')
- (/bull/g, block.bullet)
- ();
-
-block.list = replace(block.list)
- (/bull/g, block.bullet)
- ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
- ('def', '\\n+(?=' + block.def.source + ')')
- ();
-
-block.blockquote = replace(block.blockquote)
- ('def', block.def)
- ();
-
-block._tag = '(?!(?:'
- + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
- + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
- + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
-
-block.html = replace(block.html)
- ('comment', /<!--[\s\S]*?-->/)
- ('closed', /<(tag)[\s\S]+?<\/\1>/)
- ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
- (/tag/g, block._tag)
- ();
-
-block.paragraph = replace(block.paragraph)
- ('hr', block.hr)
- ('heading', block.heading)
- ('lheading', block.lheading)
- ('blockquote', block.blockquote)
- ('tag', '<' + block._tag)
- ('def', block.def)
- ();
-
-/**
- * Normal Block Grammar
- */
-
-block.normal = merge({}, block);
-
-/**
- * GFM Block Grammar
- */
-
-block.gfm = merge({}, block.normal, {
- fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
- paragraph: /^/
-});
-
-block.gfm.paragraph = replace(block.paragraph)
- ('(?!', '(?!'
- + block.gfm.fences.source.replace('\\1', '\\2') + '|'
- + block.list.source.replace('\\1', '\\3') + '|')
- ();
-
-/**
- * GFM + Tables Block Grammar
- */
-
-block.tables = merge({}, block.gfm, {
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
-});
-
-/**
- * Block Lexer
- */
-
-function Lexer(options) {
- this.tokens = [];
- this.tokens.links = {};
- this.options = options || marked.defaults;
- this.rules = block.normal;
-
- if (this.options.gfm) {
- if (this.options.tables) {
- this.rules = block.tables;
- } else {
- this.rules = block.gfm;
- }
- }
-}
-
-/**
- * Expose Block Rules
- */
-
-Lexer.rules = block;
-
-/**
- * Static Lex Method
- */
-
-Lexer.lex = function(src, options) {
- var lexer = new Lexer(options);
- return lexer.lex(src);
-};
-
-/**
- * Preprocessing
- */
-
-Lexer.prototype.lex = function(src) {
- src = src
- .replace(/\r\n|\r/g, '\n')
- .replace(/\t/g, ' ')
- .replace(/\u00a0/g, ' ')
- .replace(/\u2424/g, '\n');
-
- return this.token(src, true);
-};
-
-/**
- * Lexing
- */
-
-Lexer.prototype.token = function(src, top, bq) {
- var src = src.replace(/^ +$/gm, '')
- , next
- , loose
- , cap
- , bull
- , b
- , item
- , space
- , i
- , l;
-
- while (src) {
- // newline
- if (cap = this.rules.newline.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[0].length > 1) {
- this.tokens.push({
- type: 'space'
- });
- }
- }
-
- // code
- if (cap = this.rules.code.exec(src)) {
- src = src.substring(cap[0].length);
- cap = cap[0].replace(/^ {4}/gm, '');
- this.tokens.push({
- type: 'code',
- text: !this.options.pedantic
- ? cap.replace(/\n+$/, '')
- : cap
- });
- continue;
- }
-
- // fences (gfm)
- if (cap = this.rules.fences.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'code',
- lang: cap[2],
- text: cap[3]
- });
- continue;
- }
-
- // heading
- if (cap = this.rules.heading.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'heading',
- depth: cap[1].length,
- text: cap[2]
- });
- continue;
- }
-
- // table no leading pipe (gfm)
- if (top && (cap = this.rules.nptable.exec(src))) {
- src = src.substring(cap[0].length);
-
- item = {
- type: 'table',
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3].replace(/\n$/, '').split('\n')
- };
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = 'right';
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = 'center';
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = 'left';
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i].split(/ *\| */);
- }
-
- this.tokens.push(item);
-
- continue;
- }
-
- // lheading
- if (cap = this.rules.lheading.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'heading',
- depth: cap[2] === '=' ? 1 : 2,
- text: cap[1]
- });
- continue;
- }
-
- // hr
- if (cap = this.rules.hr.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'hr'
- });
- continue;
- }
-
- // blockquote
- if (cap = this.rules.blockquote.exec(src)) {
- src = src.substring(cap[0].length);
-
- this.tokens.push({
- type: 'blockquote_start'
- });
-
- cap = cap[0].replace(/^ *> ?/gm, '');
-
- // Pass `top` to keep the current
- // "toplevel" state. This is exactly
- // how markdown.pl works.
- this.token(cap, top, true);
-
- this.tokens.push({
- type: 'blockquote_end'
- });
-
- continue;
- }
-
- // list
- if (cap = this.rules.list.exec(src)) {
- src = src.substring(cap[0].length);
- bull = cap[2];
-
- this.tokens.push({
- type: 'list_start',
- ordered: bull.length > 1
- });
-
- // Get each top-level item.
- cap = cap[0].match(this.rules.item);
-
- next = false;
- l = cap.length;
- i = 0;
-
- for (; i < l; i++) {
- item = cap[i];
-
- // Remove the list item's bullet
- // so it is seen as the next token.
- space = item.length;
- item = item.replace(/^ *([*+-]|\d+\.) +/, '');
-
- // Outdent whatever the
- // list item contains. Hacky.
- if (~item.indexOf('\n ')) {
- space -= item.length;
- item = !this.options.pedantic
- ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
- : item.replace(/^ {1,4}/gm, '');
- }
-
- // Determine whether the next list item belongs here.
- // Backpedal if it does not belong in this list.
- if (this.options.smartLists && i !== l - 1) {
- b = block.bullet.exec(cap[i + 1])[0];
- if (bull !== b && !(bull.length > 1 && b.length > 1)) {
- src = cap.slice(i + 1).join('\n') + src;
- i = l - 1;
- }
- }
-
- // Determine whether item is loose or not.
- // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
- // for discount behavior.
- loose = next || /\n\n(?!\s*$)/.test(item);
- if (i !== l - 1) {
- next = item.charAt(item.length - 1) === '\n';
- if (!loose) loose = next;
- }
-
- this.tokens.push({
- type: loose
- ? 'loose_item_start'
- : 'list_item_start'
- });
-
- // Recurse.
- this.token(item, false, bq);
-
- this.tokens.push({
- type: 'list_item_end'
- });
- }
-
- this.tokens.push({
- type: 'list_end'
- });
-
- continue;
- }
-
- // html
- if (cap = this.rules.html.exec(src)) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: this.options.sanitize
- ? 'paragraph'
- : 'html',
- pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
- text: cap[0]
- });
- continue;
- }
-
- // def
- if ((!bq && top) && (cap = this.rules.def.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.links[cap[1].toLowerCase()] = {
- href: cap[2],
- title: cap[3]
- };
- continue;
- }
-
- // table (gfm)
- if (top && (cap = this.rules.table.exec(src))) {
- src = src.substring(cap[0].length);
-
- item = {
- type: 'table',
- header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
- cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
- };
-
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = 'right';
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = 'center';
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = 'left';
- } else {
- item.align[i] = null;
- }
- }
-
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i]
- .replace(/^ *\| *| *\| *$/g, '')
- .split(/ *\| */);
- }
-
- this.tokens.push(item);
-
- continue;
- }
-
- // top-level paragraph
- if (top && (cap = this.rules.paragraph.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'paragraph',
- text: cap[1].charAt(cap[1].length - 1) === '\n'
- ? cap[1].slice(0, -1)
- : cap[1]
- });
- continue;
- }
-
- // text
- if (cap = this.rules.text.exec(src)) {
- // Top-level should never reach here.
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: 'text',
- text: cap[0]
- });
- continue;
- }
-
- if (src) {
- throw new
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
- }
- }
-
- return this.tokens;
-};
-
-/**
- * Inline-Level Grammar
- */
-
-var inline = {
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
- autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
- url: noop,
- tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
- link: /^!?\[(inside)\]\(href\)/,
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
- nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
- strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
- em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
- code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
- br: /^ {2,}\n(?!\s*$)/,
- del: noop,
- text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
-};
-
-inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
-inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
-
-inline.link = replace(inline.link)
- ('inside', inline._inside)
- ('href', inline._href)
- ();
-
-inline.reflink = replace(inline.reflink)
- ('inside', inline._inside)
- ();
-
-/**
- * Normal Inline Grammar
- */
-
-inline.normal = merge({}, inline);
-
-/**
- * Pedantic Inline Grammar
- */
-
-inline.pedantic = merge({}, inline.normal, {
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
-});
-
-/**
- * GFM Inline Grammar
- */
-
-inline.gfm = merge({}, inline.normal, {
- escape: replace(inline.escape)('])', '~|])')(),
- url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
- del: /^~~(?=\S)([\s\S]*?\S)~~/,
- text: replace(inline.text)
- (']|', '~]|')
- ('|', '|https?://|')
- ()
-});
-
-/**
- * GFM + Line Breaks Inline Grammar
- */
-
-inline.breaks = merge({}, inline.gfm, {
- br: replace(inline.br)('{2,}', '*')(),
- text: replace(inline.gfm.text)('{2,}', '*')()
-});
-
-/**
- * Inline Lexer & Compiler
- */
-
-function InlineLexer(links, options) {
- this.options = options || marked.defaults;
- this.links = links;
- this.rules = inline.normal;
- this.renderer = this.options.renderer || new Renderer;
- this.renderer.options = this.options;
-
- if (!this.links) {
- throw new
- Error('Tokens array requires a `links` property.');
- }
-
- if (this.options.gfm) {
- if (this.options.breaks) {
- this.rules = inline.breaks;
- } else {
- this.rules = inline.gfm;
- }
- } else if (this.options.pedantic) {
- this.rules = inline.pedantic;
- }
-}
-
-/**
- * Expose Inline Rules
- */
-
-InlineLexer.rules = inline;
-
-/**
- * Static Lexing/Compiling Method
- */
-
-InlineLexer.output = function(src, links, options) {
- var inline = new InlineLexer(links, options);
- return inline.output(src);
-};
-
-/**
- * Lexing/Compiling
- */
-
-InlineLexer.prototype.output = function(src) {
- var out = ''
- , link
- , text
- , href
- , cap;
-
- while (src) {
- // escape
- if (cap = this.rules.escape.exec(src)) {
- src = src.substring(cap[0].length);
- out += cap[1];
- continue;
- }
-
- // autolink
- if (cap = this.rules.autolink.exec(src)) {
- src = src.substring(cap[0].length);
- if (cap[2] === '@') {
- text = cap[1].charAt(6) === ':'
- ? this.mangle(cap[1].substring(7))
- : this.mangle(cap[1]);
- href = this.mangle('mailto:') + text;
- } else {
- text = escape(cap[1]);
- href = text;
- }
- out += this.renderer.link(href, null, text);
- continue;
- }
-
- // url (gfm)
- if (!this.inLink && (cap = this.rules.url.exec(src))) {
- src = src.substring(cap[0].length);
- text = escape(cap[1]);
- href = text;
- out += this.renderer.link(href, null, text);
- continue;
- }
-
- // tag
- if (cap = this.rules.tag.exec(src)) {
- if (!this.inLink && /^<a /i.test(cap[0])) {
- this.inLink = true;
- } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
- this.inLink = false;
- }
- src = src.substring(cap[0].length);
- out += this.options.sanitize
- ? escape(cap[0])
- : cap[0];
- continue;
- }
-
- // link
- if (cap = this.rules.link.exec(src)) {
- src = src.substring(cap[0].length);
- this.inLink = true;
- out += this.outputLink(cap, {
- href: cap[2],
- title: cap[3]
- });
- this.inLink = false;
- continue;
- }
-
- // reflink, nolink
- if ((cap = this.rules.reflink.exec(src))
- || (cap = this.rules.nolink.exec(src))) {
- src = src.substring(cap[0].length);
- link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
- link = this.links[link.toLowerCase()];
- if (!link || !link.href) {
- out += cap[0].charAt(0);
- src = cap[0].substring(1) + src;
- continue;
- }
- this.inLink = true;
- out += this.outputLink(cap, link);
- this.inLink = false;
- continue;
- }
-
- // strong
- if (cap = this.rules.strong.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.strong(this.output(cap[2] || cap[1]));
- continue;
- }
-
- // em
- if (cap = this.rules.em.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.em(this.output(cap[2] || cap[1]));
- continue;
- }
-
- // code
- if (cap = this.rules.code.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.codespan(escape(cap[2], true));
- continue;
- }
-
- // br
- if (cap = this.rules.br.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.br();
- continue;
- }
-
- // del (gfm)
- if (cap = this.rules.del.exec(src)) {
- src = src.substring(cap[0].length);
- out += this.renderer.del(this.output(cap[1]));
- continue;
- }
-
- // text
- if (cap = this.rules.text.exec(src)) {
- src = src.substring(cap[0].length);
- out += escape(this.smartypants(cap[0]));
- continue;
- }
-
- if (src) {
- throw new
- Error('Infinite loop on byte: ' + src.charCodeAt(0));
- }
- }
-
- return out;
-};
-
-/**
- * Compile Link
- */
-
-InlineLexer.prototype.outputLink = function(cap, link) {
- var href = escape(link.href)
- , title = link.title ? escape(link.title) : null;
-
- return cap[0].charAt(0) !== '!'
- ? this.renderer.link(href, title, this.output(cap[1]))
- : this.renderer.image(href, title, escape(cap[1]));
-};
-
-/**
- * Smartypants Transformations
- */
-
-InlineLexer.prototype.smartypants = function(text) {
- if (!this.options.smartypants) return text;
- return text
- // em-dashes
- .replace(/--/g, '\u2014')
- // opening singles
- .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
- // closing singles & apostrophes
- .replace(/'/g, '\u2019')
- // opening doubles
- .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
- // closing doubles
- .replace(/"/g, '\u201d')
- // ellipses
- .replace(/\.{3}/g, '\u2026');
-};
-
-/**
- * Mangle Links
- */
-
-InlineLexer.prototype.mangle = function(text) {
- var out = ''
- , l = text.length
- , i = 0
- , ch;
-
- for (; i < l; i++) {
- ch = text.charCodeAt(i);
- if (Math.random() > 0.5) {
- ch = 'x' + ch.toString(16);
- }
- out += '&#' + ch + ';';
- }
-
- return out;
-};
-
-/**
- * Renderer
- */
-
-function Renderer(options) {
- this.options = options || {};
-}
-
-Renderer.prototype.code = function(code, lang, escaped) {
- if (this.options.highlight) {
- var out = this.options.highlight(code, lang);
- if (out != null && out !== code) {
- escaped = true;
- code = out;
- }
- }
-
- if (!lang) {
- return '<pre><code>'
- + (escaped ? code : escape(code, true))
- + '\n</code></pre>';
- }
-
- return '<pre><code class="'
- + this.options.langPrefix
- + escape(lang, true)
- + '">'
- + (escaped ? code : escape(code, true))
- + '\n</code></pre>\n';
-};
-
-Renderer.prototype.blockquote = function(quote) {
- return '<blockquote>\n' + quote + '</blockquote>\n';
-};
-
-Renderer.prototype.html = function(html) {
- return html;
-};
-
-Renderer.prototype.heading = function(text, level, raw) {
- return '<h'
- + level
- + ' id="'
- + this.options.headerPrefix
- + raw.toLowerCase().replace(/[^\w]+/g, '-')
- + '">'
- + text
- + '</h'
- + level
- + '>\n';
-};
-
-Renderer.prototype.hr = function() {
- return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
-};
-
-Renderer.prototype.list = function(body, ordered) {
- var type = ordered ? 'ol' : 'ul';
- return '<' + type + '>\n' + body + '</' + type + '>\n';
-};
-
-Renderer.prototype.listitem = function(text) {
- return '<li>' + text + '</li>\n';
-};
-
-Renderer.prototype.paragraph = function(text) {
- return '<p>' + text + '</p>\n';
-};
-
-Renderer.prototype.table = function(header, body) {
- return '<table>\n'
- + '<thead>\n'
- + header
- + '</thead>\n'
- + '<tbody>\n'
- + body
- + '</tbody>\n'
- + '</table>\n';
-};
-
-Renderer.prototype.tablerow = function(content) {
- return '<tr>\n' + content + '</tr>\n';
-};
-
-Renderer.prototype.tablecell = function(content, flags) {
- var type = flags.header ? 'th' : 'td';
- var tag = flags.align
- ? '<' + type + ' style="text-align:' + flags.align + '">'
- : '<' + type + '>';
- return tag + content + '</' + type + '>\n';
-};
-
-// span level renderer
-Renderer.prototype.strong = function(text) {
- return '<strong>' + text + '</strong>';
-};
-
-Renderer.prototype.em = function(text) {
- return '<em>' + text + '</em>';
-};
-
-Renderer.prototype.codespan = function(text) {
- return '<code>' + text + '</code>';
-};
-
-Renderer.prototype.br = function() {
- return this.options.xhtml ? '<br/>' : '<br>';
-};
-
-Renderer.prototype.del = function(text) {
- return '<del>' + text + '</del>';
-};
-
-Renderer.prototype.link = function(href, title, text) {
- if (this.options.sanitize) {
- try {
- var prot = decodeURIComponent(unescape(href))
- .replace(/[^\w:]/g, '')
- .toLowerCase();
- } catch (e) {
- return '';
- }
- if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
- return '';
- }
- }
- var out = '<a href="' + href + '"';
- if (title) {
- out += ' title="' + title + '"';
- }
- out += '>' + text + '</a>';
- return out;
-};
-
-Renderer.prototype.image = function(href, title, text) {
- var out = '<img src="' + href + '" alt="' + text + '"';
- if (title) {
- out += ' title="' + title + '"';
- }
- out += this.options.xhtml ? '/>' : '>';
- return out;
-};
-
-/**
- * Parsing & Compiling
- */
-
-function Parser(options) {
- this.tokens = [];
- this.token = null;
- this.options = options || marked.defaults;
- this.options.renderer = this.options.renderer || new Renderer;
- this.renderer = this.options.renderer;
- this.renderer.options = this.options;
-}
-
-/**
- * Static Parse Method
- */
-
-Parser.parse = function(src, options, renderer) {
- var parser = new Parser(options, renderer);
- return parser.parse(src);
-};
-
-/**
- * Parse Loop
- */
-
-Parser.prototype.parse = function(src) {
- this.inline = new InlineLexer(src.links, this.options, this.renderer);
- this.tokens = src.reverse();
-
- var out = '';
- while (this.next()) {
- out += this.tok();
- }
-
- return out;
-};
-
-/**
- * Next Token
- */
-
-Parser.prototype.next = function() {
- return this.token = this.tokens.pop();
-};
-
-/**
- * Preview Next Token
- */
-
-Parser.prototype.peek = function() {
- return this.tokens[this.tokens.length - 1] || 0;
-};
-
-/**
- * Parse Text Tokens
- */
-
-Parser.prototype.parseText = function() {
- var body = this.token.text;
-
- while (this.peek().type === 'text') {
- body += '\n' + this.next().text;
- }
-
- return this.inline.output(body);
-};
-
-/**
- * Parse Current Token
- */
-
-Parser.prototype.tok = function() {
- switch (this.token.type) {
- case 'space': {
- return '';
- }
- case 'hr': {
- return this.renderer.hr();
- }
- case 'heading': {
- return this.renderer.heading(
- this.inline.output(this.token.text),
- this.token.depth,
- this.token.text);
- }
- case 'code': {
- return this.renderer.code(this.token.text,
- this.token.lang,
- this.token.escaped);
- }
- case 'table': {
- var header = ''
- , body = ''
- , i
- , row
- , cell
- , flags
- , j;
-
- // header
- cell = '';
- for (i = 0; i < this.token.header.length; i++) {
- flags = { header: true, align: this.token.align[i] };
- cell += this.renderer.tablecell(
- this.inline.output(this.token.header[i]),
- { header: true, align: this.token.align[i] }
- );
- }
- header += this.renderer.tablerow(cell);
-
- for (i = 0; i < this.token.cells.length; i++) {
- row = this.token.cells[i];
-
- cell = '';
- for (j = 0; j < row.length; j++) {
- cell += this.renderer.tablecell(
- this.inline.output(row[j]),
- { header: false, align: this.token.align[j] }
- );
- }
-
- body += this.renderer.tablerow(cell);
- }
- return this.renderer.table(header, body);
- }
- case 'blockquote_start': {
- var body = '';
-
- while (this.next().type !== 'blockquote_end') {
- body += this.tok();
- }
-
- return this.renderer.blockquote(body);
- }
- case 'list_start': {
- var body = ''
- , ordered = this.token.ordered;
-
- while (this.next().type !== 'list_end') {
- body += this.tok();
- }
-
- return this.renderer.list(body, ordered);
- }
- case 'list_item_start': {
- var body = '';
-
- while (this.next().type !== 'list_item_end') {
- body += this.token.type === 'text'
- ? this.parseText()
- : this.tok();
- }
-
- return this.renderer.listitem(body);
- }
- case 'loose_item_start': {
- var body = '';
-
- while (this.next().type !== 'list_item_end') {
- body += this.tok();
- }
-
- return this.renderer.listitem(body);
- }
- case 'html': {
- var html = !this.token.pre && !this.options.pedantic
- ? this.inline.output(this.token.text)
- : this.token.text;
- return this.renderer.html(html);
- }
- case 'paragraph': {
- return this.renderer.paragraph(this.inline.output(this.token.text));
- }
- case 'text': {
- return this.renderer.paragraph(this.parseText());
- }
- }
-};
-
-/**
- * Helpers
- */
-
-function escape(html, encode) {
- return html
- .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
- .replace(/</g, '&lt;')
- .replace(/>/g, '&gt;')
- .replace(/"/g, '&quot;')
- .replace(/'/g, '&#39;');
-}
-
-function unescape(html) {
- return html.replace(/&([#\w]+);/g, function(_, n) {
- n = n.toLowerCase();
- if (n === 'colon') return ':';
- if (n.charAt(0) === '#') {
- return n.charAt(1) === 'x'
- ? String.fromCharCode(parseInt(n.substring(2), 16))
- : String.fromCharCode(+n.substring(1));
- }
- return '';
- });
-}
-
-function replace(regex, opt) {
- regex = regex.source;
- opt = opt || '';
- return function self(name, val) {
- if (!name) return new RegExp(regex, opt);
- val = val.source || val;
- val = val.replace(/(^|[^\[])\^/g, '$1');
- regex = regex.replace(name, val);
- return self;
- };
-}
-
-function noop() {}
-noop.exec = noop;
-
-function merge(obj) {
- var i = 1
- , target
- , key;
-
- for (; i < arguments.length; i++) {
- target = arguments[i];
- for (key in target) {
- if (Object.prototype.hasOwnProperty.call(target, key)) {
- obj[key] = target[key];
- }
- }
- }
-
- return obj;
-}
-
-
-/**
- * Marked
- */
-
-function marked(src, opt, callback) {
- if (callback || typeof opt === 'function') {
- if (!callback) {
- callback = opt;
- opt = null;
- }
-
- opt = merge({}, marked.defaults, opt || {});
-
- var highlight = opt.highlight
- , tokens
- , pending
- , i = 0;
-
- try {
- tokens = Lexer.lex(src, opt)
- } catch (e) {
- return callback(e);
- }
-
- pending = tokens.length;
-
- var done = function(err) {
- if (err) {
- opt.highlight = highlight;
- return callback(err);
- }
-
- var out;
-
- try {
- out = Parser.parse(tokens, opt);
- } catch (e) {
- err = e;
- }
-
- opt.highlight = highlight;
-
- return err
- ? callback(err)
- : callback(null, out);
- };
-
- if (!highlight || highlight.length < 3) {
- return done();
- }
-
- delete opt.highlight;
-
- if (!pending) return done();
-
- for (; i < tokens.length; i++) {
- (function(token) {
- if (token.type !== 'code') {
- return --pending || done();
- }
- return highlight(token.text, token.lang, function(err, code) {
- if (err) return done(err);
- if (code == null || code === token.text) {
- return --pending || done();
- }
- token.text = code;
- token.escaped = true;
- --pending || done();
- });
- })(tokens[i]);
- }
-
- return;
- }
- try {
- if (opt) opt = merge({}, marked.defaults, opt);
- return Parser.parse(Lexer.lex(src, opt), opt);
- } catch (e) {
- e.message += '\nPlease report this to https://github.com/chjj/marked.';
- if ((opt || marked.defaults).silent) {
- return '<p>An error occured:</p><pre>'
- + escape(e.message + '', true)
- + '</pre>';
- }
- throw e;
- }
-}
-
-/**
- * Options
- */
-
-marked.options =
-marked.setOptions = function(opt) {
- merge(marked.defaults, opt);
- return marked;
-};
-
-marked.defaults = {
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: false,
- smartLists: false,
- silent: false,
- highlight: null,
- langPrefix: 'lang-',
- smartypants: false,
- headerPrefix: '',
- renderer: new Renderer,
- xhtml: false
-};
-
-/**
- * Expose
- */
-
-marked.Parser = Parser;
-marked.parser = Parser.parse;
-
-marked.Renderer = Renderer;
-
-marked.Lexer = Lexer;
-marked.lexer = Lexer.lex;
-
-marked.InlineLexer = InlineLexer;
-marked.inlineLexer = InlineLexer.output;
-
-marked.parse = marked;
-
-if (typeof module !== 'undefined' && typeof exports === 'object') {
- module.exports = marked;
-} else if (typeof define === 'function' && define.amd) {
- define(function() { return marked; });
-} else {
- this.marked = marked;
-}
-
-}).call(function() {
- return this || (typeof window !== 'undefined' ? window : global);
-}());
diff --git a/js/vendor/marked/man/marked.1 b/js/vendor/marked/man/marked.1
deleted file mode 100644
index f89f1a7b..00000000
--- a/js/vendor/marked/man/marked.1
+++ /dev/null
@@ -1,88 +0,0 @@
-.ds q \N'34'
-.TH marked 1 "2014-01-31" "v0.3.1" "marked.js"
-
-.SH NAME
-marked \- a javascript markdown parser
-
-.SH SYNOPSIS
-.B marked
-[\-o \fI<output>\fP] [\-i \fI<input>\fP] [\-\-help]
-[\-\-tokens] [\-\-pedantic] [\-\-gfm]
-[\-\-breaks] [\-\-tables] [\-\-sanitize]
-[\-\-smart\-lists] [\-\-lang\-prefix \fI<prefix>\fP]
-[\-\-no\-etc...] [\-\-silent] [\fIfilename\fP]
-
-.SH DESCRIPTION
-.B marked
-is a full-featured javascript markdown parser, built for speed. It also includes
-multiple GFM features.
-
-.SH EXAMPLES
-.TP
-cat in.md | marked > out.html
-.TP
-echo "hello *world*" | marked
-.TP
-marked \-o out.html in.md \-\-gfm
-.TP
-marked \-\-output="hello world.html" \-i in.md \-\-no-breaks
-
-.SH OPTIONS
-.TP
-.BI \-o,\ \-\-output\ [\fIoutput\fP]
-Specify file output. If none is specified, write to stdout.
-.TP
-.BI \-i,\ \-\-input\ [\fIinput\fP]
-Specify file input, otherwise use last argument as input file. If no input file
-is specified, read from stdin.
-.TP
-.BI \-t,\ \-\-tokens
-Output a token stream instead of html.
-.TP
-.BI \-\-pedantic
-Conform to obscure parts of markdown.pl as much as possible. Don't fix original
-markdown bugs.
-.TP
-.BI \-\-gfm
-Enable github flavored markdown.
-.TP
-.BI \-\-breaks
-Enable GFM line breaks. Only works with the gfm option.
-.TP
-.BI \-\-tables
-Enable GFM tables. Only works with the gfm option.
-.TP
-.BI \-\-sanitize
-Sanitize output. Ignore any HTML input.
-.TP
-.BI \-\-smart\-lists
-Use smarter list behavior than the original markdown.
-.TP
-.BI \-\-lang\-prefix\ [\fIprefix\fP]
-Set the prefix for code block classes.
-.TP
-.BI \-\-no\-sanitize,\ \-no-etc...
-The inverse of any of the marked options above.
-.TP
-.BI \-\-silent
-Silence error output.
-.TP
-.BI \-h,\ \-\-help
-Display help information.
-
-.SH CONFIGURATION
-For configuring and running programmatically.
-
-.B Example
-
- require('marked')('*foo*', { gfm: true });
-
-.SH BUGS
-Please report any bugs to https://github.com/chjj/marked.
-
-.SH LICENSE
-Copyright (c) 2011-2014, Christopher Jeffrey (MIT License).
-
-.SH "SEE ALSO"
-.BR markdown(1),
-.BR node.js(1)
diff --git a/js/vendor/marked/package.json b/js/vendor/marked/package.json
deleted file mode 100644
index eb1e28db..00000000
--- a/js/vendor/marked/package.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "name": "marked",
- "description": "A markdown parser built for speed",
- "author": "Christopher Jeffrey",
- "version": "0.3.3",
- "main": "./lib/marked.js",
- "bin": "./bin/marked",
- "man": "./man/marked.1",
- "preferGlobal": true,
- "repository": "git://github.com/chjj/marked.git",
- "homepage": "https://github.com/chjj/marked",
- "bugs": { "url": "http://github.com/chjj/marked/issues" },
- "license": "MIT",
- "keywords": ["markdown", "markup", "html"],
- "tags": ["markdown", "markup", "html"],
- "devDependencies": {
- "markdown": "*",
- "showdown": "*",
- "robotskirt": "*"
- },
- "scripts": { "test": "node test", "bench": "node test --bench" }
-}