<commit_before>/*
Copyright (c) 2013 Ritchie Thai

See the file license.txt for copying permission.
*/

adventure.getSceneManager = function (util) {

    var each = util.each;

    var nullObjectHotspot = {description: '', shape: {type: ''}, onArrive: function () {}};

    var currentScene,
        backgroundDirectory,
        uiManager,
        conversationManager,
        sceneFunctions,
        scenes;

    var configure = function (configuration) {
        backgroundDirectory    = configuration.backgroundDirectory;
        uiManager = configuration.uiManager;
        conversationManager = configuration.conversationManager;
        sceneFunctions = configuration.sceneFunctions;
        scenes = configuration.scenes;
    };

    var putPlayerAt = function (x, y)  {
        uiManager.putPlayerAt({x: x, y: y});
    };

    var putPlayerAtPoint = function (point) {
        putPlayerAt(point.x, point.y);
    };

    var facePlayerLeft = function () {
        uiManager.facePlayerLeft();
    };

    var facePlayerRight = function () {
        uiManager.facePlayerRight();
    };

    var movePlayer = function (destination, callback) {
        uiManager.movePlayer(destination, callback)
    };

    var pointIsInShape = function (point, shape) {
        var topLeftCorner = shape.topLeftCorner;
        var bottomRightCorner = shape.bottomRightCorner;
        var result =
            shape.type === "rectangle" &&
            point.x >= topLeftCorner.x &&
            point.x <= bottomRightCorner.x &&
            point.y >= topLeftCorner.y &&
            point.y <= bottomRightCorner.y;
        return result;
    };

    var getHotspotAt = function (point) {
        var hotspots = currentScene.hotspots;
        for (var i = 0; i < hotspots.length; i += 1) {
            var hotspot = hotspots[i];
            if (!hotspot.hidden && pointIsInShape(point, hotspot.shape)) {
                return hotspot;
            }
        }
        return nullObjectHotspot;
    };

    var isInConversation = function () {
        return conversationManager.isInConversation();
    };

    var hideSceneImageById = function (id) {
        each(currentScene.images, function (image) {
            if (image.id === id) {
                image.hidden = true;
            }
        });
        uiManager.hideSceneImageById(id);
    };

    var flipSceneImageById = function (id) {
        each(currentScene.images, function (image) {
            if (image.id === id) {
                image.isFlipped = true;
            }
        });
        uiManager.flipSceneImageById(id);
    };

    var hideHotspotById = function (id) {
        each(currentScene.hotspots, function(hotspot) {
            if (hotspot.id === id) {
                hotspot.hidden = true;
            }
        });
    };

    var performPreventableSceneActions = function (scene) {
        var position = scene.playerPositionOnEnter;
        if (position) {
            putPlayerAtPoint(position);
        }
        var conversation = scene.conversationToStartOnEnter;
        if (conversation) {
            conversationManager.startConversation(conversation);
        }
    };

    var performSceneActions = function (scene) {
        if (scene.onEnter) {
            var sceneFunction = sceneFunctions[scene.onEnter];
            var onEnterResult = sceneFunction(scene);
            shouldPreventDefault = onEnterResult !== false;
            if (shouldPreventDefault) { return; }
        }
        performPreventableSceneActions(scene);
    };

    var loadScene = function (scene) {
        var scope = {};
        var controller = sceneFunctions[scene.controller];
        if (controller) { controller(scope); }
        var evaluatedScene = evaluateShowCondition(scene, scope);
        performSceneActions(evaluatedScene);
        uiManager.drawScene(evaluatedScene, backgroundDirectory);
        currentScene = evaluatedScene;
    };

    var evaluateShowCondition = function (scene, scope) {
        var newScene = util.clone(scene);
        newScene.images = evaluateShowConditionOnElements(scene.images, scope);
        newScene.hotspots = evaluateShowConditionOnElements(scene.hotspots, scope);
        return newScene;
    };

    var evaluateShowConditionOnElements = function (elements, scope) {
        var newElements = util.clone(elements);
        each(newElements, function (element) {
            if (element.hasOwnProperty('showCondition') && !scope[element.showCondition]) {
                element.hidden = true;
            }
        });
        return newElements;
    };

    var loadSceneByName = function (name) {
        loadScene(scenes[name]);
    };

    var hitHotspot = function (coordinates) {
        var hotspot = getHotspotAt(coordinates);
        if (hotspot.onHit) {
            var onHitResult = sceneFunctions[hotspot.onHit]();
            var shouldPreventDefault = onHitResult === false;
            if (shouldPreventDefault) { return; }
        }
        if (isInConversation()) return;
        onHitHotspotWhereOnHitAllowsDefault(coordinates, hotspot);
    };

    var onHitHotspotWhereOnHitAllowsDefault = function (clickedPoint, hotspot) {
        if (hotspot.positionToMovePlayerTo) {
            movePlayerToHotspot(hotspot);
        }
        if (hotspot.conversationToStart) {
            conversationManager.startConversation(hotspot.conversationToStart);
        }
        if (shouldMoveToClickedPoint(hotspot)) {
            movePlayer(clickedPoint, function () { onArrive(clickedPoint); });
        } else if (hotspot.shouldStandStill) {
            // TODO: A bit hacky. 50 seconds to debounce
            // Android's use of both click and touch events
            setTimeout(function () { onArrive(clickedPoint); }, 50);
        }
    };

    var shouldMoveToClickedPoint = function (hotspot) {
        return !(hotspot.shouldPreventDefault || hotspot.isSolid || hotspot.shouldStandStill ||
            hotspot.positionToMovePlayerTo || hotspot.conversationToStart);
    };

    var movePlayerToHotspot = function (hotspot) {
        movePlayer(hotspot.positionToMovePlayerTo, function () {
            uiManager.makePlayerFaceRightWayForMove(hotspot.shape.bottomRightCorner);
        });
    };

    var onArrive = function (event) {
        var hotspot = getHotspotAt(event);
        if (hotspot.onArrive) { hotspot.onArrive() };
        if (hotspot.destinationScene) {
            loadScene(scenes[hotspot.destinationScene]);
        }
        if (hotspot.destinationPosition) {
            putPlayerAt(
                hotspot.destinationPosition.x, hotspot.destinationPosition.y);
        }
    };

    var sceneManagerToReturn = {
        getHotspotAt: getHotspotAt,
        putPlayerAt: putPlayerAt,
        movePlayer: movePlayer,
        facePlayerLeft: facePlayerLeft,
        facePlayerRight: facePlayerRight,
        loadScene: loadScene,
        loadSceneByName: loadSceneByName,
        hideSceneImageById: hideSceneImageById,
        flipSceneImageById: flipSceneImageById,
        hideHotspotById: hideHotspotById,
        isInConversation: isInConversation,
        hitHotspot: hitHotspot,
        configure: configure
    };

    return sceneManagerToReturn;
};
<commit_msg>Reorder functions in scene manager<commit_after>/*
Copyright (c) 2013 Ritchie Thai

See the file license.txt for copying permission.
*/

adventure.getSceneManager = function (util) {

    var each = util.each;

    var nullObjectHotspot = {description: '', shape: {type: ''}, onArrive: function () {}};

    var currentScene,
        backgroundDirectory,
        uiManager,
        conversationManager,
        sceneFunctions,
        scenes;

    var configure = function (configuration) {
        backgroundDirectory    = configuration.backgroundDirectory;
        uiManager = configuration.uiManager;
        conversationManager = configuration.conversationManager;
        sceneFunctions = configuration.sceneFunctions;
        scenes = configuration.scenes;
    };

    var putPlayerAt = function (x, y)  {
        uiManager.putPlayerAt({x: x, y: y});
    };

    var putPlayerAtPoint = function (point) {
        putPlayerAt(point.x, point.y);
    };

    var facePlayerLeft = function () {
        uiManager.facePlayerLeft();
    };

    var facePlayerRight = function () {
        uiManager.facePlayerRight();
    };

    var movePlayer = function (destination, callback) {
        uiManager.movePlayer(destination, callback)
    };

    var pointIsInShape = function (point, shape) {
        var topLeftCorner = shape.topLeftCorner;
        var bottomRightCorner = shape.bottomRightCorner;
        var result =
            shape.type === "rectangle" &&
            point.x >= topLeftCorner.x &&
            point.x <= bottomRightCorner.x &&
            point.y >= topLeftCorner.y &&
            point.y <= bottomRightCorner.y;
        return result;
    };

    var getHotspotAt = function (point) {
        var hotspots = currentScene.hotspots;
        for (var i = 0; i < hotspots.length; i += 1) {
            var hotspot = hotspots[i];
            if (!hotspot.hidden && pointIsInShape(point, hotspot.shape)) {
                return hotspot;
            }
        }
        return nullObjectHotspot;
    };

    var isInConversation = function () {
        return conversationManager.isInConversation();
    };

    var hideSceneImageById = function (id) {
        each(currentScene.images, function (image) {
            if (image.id === id) {
                image.hidden = true;
            }
        });
        uiManager.hideSceneImageById(id);
    };

    var flipSceneImageById = function (id) {
        each(currentScene.images, function (image) {
            if (image.id === id) {
                image.isFlipped = true;
            }
        });
        uiManager.flipSceneImageById(id);
    };

    var hideHotspotById = function (id) {
        each(currentScene.hotspots, function(hotspot) {
            if (hotspot.id === id) {
                hotspot.hidden = true;
            }
        });
    };

    var loadSceneByName = function (name) {
        loadScene(scenes[name]);
    };

    var loadScene = function (scene) {
        var scope = {};
        var controller = sceneFunctions[scene.controller];
        if (controller) { controller(scope); }
        var evaluatedScene = evaluateShowCondition(scene, scope);
        performSceneActions(evaluatedScene);
        uiManager.drawScene(evaluatedScene, backgroundDirectory);
        currentScene = evaluatedScene;
    };

    var evaluateShowCondition = function (scene, scope) {
        var newScene = util.clone(scene);
        newScene.images = evaluateShowConditionOnElements(scene.images, scope);
        newScene.hotspots = evaluateShowConditionOnElements(scene.hotspots, scope);
        return newScene;
    };

    var evaluateShowConditionOnElements = function (elements, scope) {
        var newElements = util.clone(elements);
        each(newElements, function (element) {
            if (element.hasOwnProperty('showCondition') && !scope[element.showCondition]) {
                element.hidden = true;
            }
        });
        return newElements;
    };

    var performSceneActions = function (scene) {
        if (scene.onEnter) {
            var sceneFunction = sceneFunctions[scene.onEnter];
            var onEnterResult = sceneFunction(scene);
            shouldPreventDefault = onEnterResult !== false;
            if (shouldPreventDefault) { return; }
        }
        performPreventableSceneActions(scene);
    };

    var performPreventableSceneActions = function (scene) {
        var position = scene.playerPositionOnEnter;
        if (position) {
            putPlayerAtPoint(position);
        }
        var conversation = scene.conversationToStartOnEnter;
        if (conversation) {
            conversationManager.startConversation(conversation);
        }
    };

    var hitHotspot = function (coordinates) {
        var hotspot = getHotspotAt(coordinates);
        if (hotspot.onHit) {
            var onHitResult = sceneFunctions[hotspot.onHit]();
            var shouldPreventDefault = onHitResult === false;
            if (shouldPreventDefault) { return; }
        }
        if (isInConversation()) return;
        onHitHotspotWhereOnHitAllowsDefault(coordinates, hotspot);
    };

    var onHitHotspotWhereOnHitAllowsDefault = function (clickedPoint, hotspot) {
        if (hotspot.positionToMovePlayerTo) {
            movePlayerToHotspot(hotspot);
        }
        if (hotspot.conversationToStart) {
            conversationManager.startConversation(hotspot.conversationToStart);
        }
        if (shouldMoveToClickedPoint(hotspot)) {
            movePlayer(clickedPoint, function () { onArrive(clickedPoint); });
        } else if (hotspot.shouldStandStill) {
            // TODO: A bit hacky. 50 seconds to debounce
            // Android's use of both click and touch events
            setTimeout(function () { onArrive(clickedPoint); }, 50);
        }
    };

    var shouldMoveToClickedPoint = function (hotspot) {
        return !(hotspot.shouldPreventDefault || hotspot.isSolid || hotspot.shouldStandStill ||
            hotspot.positionToMovePlayerTo || hotspot.conversationToStart);
    };

    var movePlayerToHotspot = function (hotspot) {
        movePlayer(hotspot.positionToMovePlayerTo, function () {
            uiManager.makePlayerFaceRightWayForMove(hotspot.shape.bottomRightCorner);
        });
    };

    var onArrive = function (event) {
        var hotspot = getHotspotAt(event);
        if (hotspot.onArrive) { hotspot.onArrive() };
        if (hotspot.destinationScene) {
            loadScene(scenes[hotspot.destinationScene]);
        }
        if (hotspot.destinationPosition) {
            putPlayerAt(
                hotspot.destinationPosition.x, hotspot.destinationPosition.y);
        }
    };

    var sceneManagerToReturn = {
        getHotspotAt: getHotspotAt,
        putPlayerAt: putPlayerAt,
        movePlayer: movePlayer,
        facePlayerLeft: facePlayerLeft,
        facePlayerRight: facePlayerRight,
        loadScene: loadScene,
        loadSceneByName: loadSceneByName,
        hideSceneImageById: hideSceneImageById,
        flipSceneImageById: flipSceneImageById,
        hideHotspotById: hideHotspotById,
        isInConversation: isInConversation,
        hitHotspot: hitHotspot,
        configure: configure
    };

    return sceneManagerToReturn;
};
<|endoftext|>


<commit_before>//
//  Created by Mickaël Menu.
//  Modified by Juan Corona.
//  Portions adapted from Rangy's Module system: Copyright (c) 2014 Tim Down
//
//  Copyright (c) 2014 Readium Foundation and/or its licensees. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met:
//  1. Redistributions of source code must retain the above copyright notice, this
//  list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//  this list of conditions and the following disclaimer in the documentation and/or
//  other materials provided with the distribution.
//  3. Neither the name of the organization nor the names of its contributors may be
//  used to endorse or promote products derived from this software without specific
//  prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
//  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
//  OF THE POSSIBILITY OF SUCH DAMAGE.

//
// A lightweight plugins controller used to easily add plugins from the host
// app, eg.
//
//   ReadiumSDK.plugins.load(FootnotePlugin, true);
//
// The controller will create a new instance of the plugin, forwarding any given
// arguments. Then, on several useful common Readium notifications, the
// controller will call predefined callbacks if implemented in the plug-in.
//
// Supported callbacks are:
//      onReaderInitialized()
//      onDocumentLoadStart($iframe, spineItem)
//      onDocumentLoadedBeforeInjection($iframe, $document, spineItem);
//      onDocumentLoaded($iframe, $document, spineItem);
//

function PluginApi(reader, plugin) {
    this.reader = reader;
    this.plugin = plugin;

    this.extendReader = function (extendWith) {
        var obj = {};
        obj[plugin.name] = extendWith;
        _(ReadiumSDK.Views.ReaderView.prototype).extend(obj);
    };
}

function PluginApiFactory(reader) {
    this.create = function (plugin) {
        return new PluginApi(reader, plugin);
    }
}

function PluginsController() {
    var self = this;

    var _plugins = [];

    function _initializePlugins(reader) {
        var plugin,
            apiFactory = new PluginApiFactory(reader);

        for (var pluginName in _plugins) {
            if ((plugin = _plugins[pluginName]) instanceof Plugin) {
                plugin.init(apiFactory);
            }
        }
    }

    function _getExceptionMessage(ex) {
        return ex.message || ex.description || String(ex);
    }

    // Creates a new instance of the given plugin constructor.
    this.loadPlugin = function (name, optDependencies, initFunc) {

        var dependencies;
        if (typeof optDependencies === 'function') {
            initFunc = optDependencies;
        } else {
            dependencies = optDependencies;
        }

        this.plugins[name] = new Plugin(name, dependencies, function (plugin, api) {
            if (!plugin.initialized) {
                plugin.initialized = true;
                try {
                    initFunc.call({}, api);
                    plugin.supported = true;
                } catch (ex) {
                    plugin.fail(_getExceptionMessage(ex));
                }
            }
        });
    };

    ReadiumSDK.on(ReadiumSDK.Events.READER_INITIALIZED, function (reader) {

        try {
            _initializePlugins(reader);
        } catch (ex) {
            console.error("Plugins failed to initialize:" + _getExceptionMessage(ex));
        }

        _.defer(function () {
            ReadiumSDK.trigger(ReadiumSDK.Events.PLUGINS_LOADED);
        });
    });
}

ReadiumSDK.Plugins = new PluginsController();

//
//  The following is adapted from Rangy's Module class:
//
//  Copyright (c) 2014 Tim Down
//
//  The MIT License (MIT)
//  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.

function Plugin(name, dependencies, initializer) {
    this.name = name;
    this.dependencies = dependencies;
    this.initialized = false;
    this.supported = false;
    this.initializer = initializer;
}

Plugin.prototype = {
    init: function (apiFactory) {
        var requiredPluginNames = this.dependencies || [];
        for (var i = 0, len = requiredPluginNames.length, requiredPlugin, PluginName; i < len; ++i) {
            PluginName = requiredPluginNames[i];

            requiredPlugin = Plugins[PluginName];
            if (!requiredPlugin || !(requiredPlugin instanceof Plugin)) {
                throw new Error("required Plugin '" + PluginName + "' not found");
            }

            requiredPlugin.init(apiFactory);

            if (!requiredPlugin.supported) {
                throw new Error("required Plugin '" + PluginName + "' not supported");
            }
        }

        // Now run initializer
        this.initializer(this, apiFactory.create(this));
    },

    fail: function (reason) {
        this.initialized = true;
        this.supported = false;
        throw new Error("Plugin '" + this.name + "' failed to load: " + reason);
    },

    warn: function (msg) {
        console.warn("Plugin " + this.name + ": " + msg);
    },

    deprecationNotice: function (deprecated, replacement) {
        console.warn("DEPRECATED: " + deprecated + " in Plugin " + this.name + "is deprecated. Please use "
            + replacement + " instead");
    },

    createError: function (msg) {
        return new Error("Error in " + this.name + " Plugin: " + msg);
    }
};<commit_msg>Properly contain plugin extensions added to the reader object.<commit_after>//
//  Created by Mickaël Menu.
//  Modified by Juan Corona.
//  Portions adapted from Rangy's Module system: Copyright (c) 2014 Tim Down
//
//  Copyright (c) 2014 Readium Foundation and/or its licensees. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without modification,
//  are permitted provided that the following conditions are met:
//  1. Redistributions of source code must retain the above copyright notice, this
//  list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright notice,
//  this list of conditions and the following disclaimer in the documentation and/or
//  other materials provided with the distribution.
//  3. Neither the name of the organization nor the names of its contributors may be
//  used to endorse or promote products derived from this software without specific
//  prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
//  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
//  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
//  OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
//  OF THE POSSIBILITY OF SUCH DAMAGE.

//
// A lightweight plugins controller used to easily add plugins from the host
// app, eg.
//
//   ReadiumSDK.plugins.load(FootnotePlugin, true);
//
// The controller will create a new instance of the plugin, forwarding any given
// arguments. Then, on several useful common Readium notifications, the
// controller will call predefined callbacks if implemented in the plug-in.
//
// Supported callbacks are:
//      onReaderInitialized()
//      onDocumentLoadStart($iframe, spineItem)
//      onDocumentLoadedBeforeInjection($iframe, $document, spineItem);
//      onDocumentLoaded($iframe, $document, spineItem);
//

function PluginApi(reader, plugin) {
    this.reader = reader;
    this.plugin = plugin;

    this.extendReader = function (extendWith) {
        if (reader.plugins) {
            var obj = {};
            obj[plugin.name] = extendWith;

            _(reader.plugins).extend(obj);
        }
    };
}

function PluginApiFactory(reader) {
    this.create = function (plugin) {
        return new PluginApi(reader, plugin);
    }
}

function PluginsController() {
    var self = this;

    var _plugins = [];

    function _initializePlugins(reader) {
        var plugin,
            apiFactory = new PluginApiFactory(reader);

        if (!reader.plugins) {
            //attach an object to the reader that will be
            // used for plugin namespaces and their extensions
            reader.plugins = {};
        } else {
            throw new Error("Already initialized on reader!");
        }

        for (var pluginName in _plugins) {
            if ((plugin = _plugins[pluginName]) instanceof Plugin) {
                plugin.init(apiFactory);
            }
        }
    }

    function _getExceptionMessage(ex) {
        return ex.message || ex.description || String(ex);
    }

    // Creates a new instance of the given plugin constructor.
    this.loadPlugin = function (name, optDependencies, initFunc) {

        var dependencies;
        if (typeof optDependencies === 'function') {
            initFunc = optDependencies;
        } else {
            dependencies = optDependencies;
        }

        this.plugins[name] = new Plugin(name, dependencies, function (plugin, api) {
            if (!plugin.initialized) {
                plugin.initialized = true;
                try {
                    initFunc.call({}, api);
                    plugin.supported = true;
                } catch (ex) {
                    plugin.fail(_getExceptionMessage(ex));
                }
            }
        });
    };

    ReadiumSDK.on(ReadiumSDK.Events.READER_INITIALIZED, function (reader) {

        try {
            _initializePlugins(reader);
        } catch (ex) {
            console.error("Plugins failed to initialize:" + _getExceptionMessage(ex));
        }

        _.defer(function () {
            ReadiumSDK.trigger(ReadiumSDK.Events.PLUGINS_LOADED);
        });
    });
}

ReadiumSDK.Plugins = new PluginsController();

//
//  The following is adapted from Rangy's Module class:
//
//  Copyright (c) 2014 Tim Down
//
//  The MIT License (MIT)
//  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.

function Plugin(name, dependencies, initializer) {
    this.name = name;
    this.dependencies = dependencies;
    this.initialized = false;
    this.supported = false;
    this.initializer = initializer;
}

Plugin.prototype = {
    init: function (apiFactory) {
        var requiredPluginNames = this.dependencies || [];
        for (var i = 0, len = requiredPluginNames.length, requiredPlugin, PluginName; i < len; ++i) {
            PluginName = requiredPluginNames[i];

            requiredPlugin = Plugins[PluginName];
            if (!requiredPlugin || !(requiredPlugin instanceof Plugin)) {
                throw new Error("required Plugin '" + PluginName + "' not found");
            }

            requiredPlugin.init(apiFactory);

            if (!requiredPlugin.supported) {
                throw new Error("required Plugin '" + PluginName + "' not supported");
            }
        }

        // Now run initializer
        this.initializer(this, apiFactory.create(this));
    },

    fail: function (reason) {
        this.initialized = true;
        this.supported = false;
        throw new Error("Plugin '" + this.name + "' failed to load: " + reason);
    },

    warn: function (msg) {
        console.warn("Plugin " + this.name + ": " + msg);
    },

    deprecationNotice: function (deprecated, replacement) {
        console.warn("DEPRECATED: " + deprecated + " in Plugin " + this.name + "is deprecated. Please use "
            + replacement + " instead");
    },

    createError: function (msg) {
        return new Error("Error in " + this.name + " Plugin: " + msg);
    }
};<|endoftext|>


<commit_before>'use strict';

// Constants and fixed parameters
const BASE_TITLE = 'Historical Markers Map – Encyclopedia of Philippine Heritage';
const LANGUAGES = {
  'en'  : { name: 'English', qid: 'Q1860'  },
  'tl'  : { name: 'Tagalog', qid: 'Q34057' },
  'ceb' : { name: 'Cebuano', qid: 'Q33239' },
  'ilo' : { name: 'Ilocano', qid: 'Q35936' },
  'es'  : { name: 'Spanish', qid: 'Q1321'  },
  'de'  : { name: 'German' , qid: 'Q188'   },
  'fr'  : { name: 'French' , qid: 'Q150'   },
};
const ORDERED_LANGUAGES = ['en', 'tl', 'ceb', 'ilo', 'es', 'de', 'fr'];
const NL = '\n';
const SPARQL_QUERY =
'SELECT ?marker ?markerLabel ?coord ?title ?subtitle ?titleNoValue ?image' + NL +
'       ?date ?datePrecision ?inscription ?inscriptionNoValue' + NL +
'       ?country ?countryLabel ?locationLabel ?locationImage ?streetAddress' + NL +
'       ?admin0Label ?admin0Type ?admin1Label ?admin1Type' + NL +
'       ?admin2Label ?admin2Type ?admin3Label ?admin3Type' + NL +
'       ?vicinityImage ?vicinityDescription' + NL +
'       ?commemorates ?commemoratesLabel ?commemoratesArticle WHERE {' + NL +
'  ?marker wdt:P31 wd:Q21562164 ;' + NL +
'          wdt:P625 ?coord .' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P1476 ?titleStatement .' + NL +
'    OPTIONAL {' + NL +
'      ?titleStatement ps:P1476 ?title .' + NL +
'      OPTIONAL { ?titleStatement pq:P1680 ?subtitle }' + NL +
'    }' + NL +
'    OPTIONAL {' + NL +
'      ?titleStatement a ?titleNoValue .' + NL +
'      FILTER (?titleNoValue = wdno:P1476)' + NL +
'    }' + NL +
'  }' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P18 ?imageStatement .' + NL +
'    OPTIONAL {' + NL +
'      ?imageStatement ps:P18 ?image .' + NL +
'      FILTER NOT EXISTS { ?imageStatement pq:P3831 wd:Q16968816 }' + NL +
'    }' + NL +
'    OPTIONAL {' + NL +
'      ?imageStatement ps:P18 ?vicinityImage .' + NL +
'      OPTIONAL { ?imageStatement pq:P2096 ?vicinityDescription }' + NL +
'      FILTER EXISTS { ?imageStatement pq:P3831 wd:Q16968816 }' + NL +
'    }' + NL +
'  }' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P571 ?dateStatement .' + NL +
'    ?dateStatement psv:P571 ?dateValue .' + NL +
'    ?dateValue wikibase:timeValue ?date .' + NL +
'    ?dateValue wikibase:timePrecision ?datePrecision .' + NL +
'  }' + NL +
'  OPTIONAL { ?marker wdt:P1684 ?inscription }' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P1684 ?inscriptionStatement .' + NL +
'    ?inscriptionStatement a ?inscriptionNoValue .' + NL +
'    FILTER (?inscriptionNoValue = wdno:P1684)' + NL +
'  }' + NL +
'  OPTIONAL { ?marker wdt:P17 ?country }' + NL +
'  OPTIONAL {' + NL +
'    ?marker wdt:P276 ?location .' + NL +
'    OPTIONAL { ?location wdt:P18 ?locationImage }' + NL +
'  }' + NL +
'  OPTIONAL { ?marker wdt:P969 ?streetAddress }' + NL +
'  OPTIONAL {' + NL +
'    ?marker wdt:P131 ?admin0 .' + NL +
'    OPTIONAL {' + NL +
'      ?admin0 wdt:P31 ?admin0Type .' + NL +
'      FILTER (' + NL +
'        ?admin0Type = wd:Q6256   ||' + NL +
'        ?admin0Type = wd:Q24698  ||' + NL +
'        ?admin0Type = wd:Q24746  ||' + NL +
'        ?admin0Type = wd:Q104157 ||' + NL +
'        ?admin0Type = wd:Q29946056' + NL +
'      )' + NL +
'    }' + NL +
'    OPTIONAL {' + NL +
'      ?admin0 wdt:P131 ?admin1 .' + NL +
'      OPTIONAL {' + NL +
'        ?admin1 wdt:P31 ?admin1Type .' + NL +
'        FILTER (' + NL +
'          ?admin1Type = wd:Q6256   ||' + NL +
'          ?admin1Type = wd:Q24698  ||' + NL +
'          ?admin1Type = wd:Q24746  ||' + NL +
'          ?admin1Type = wd:Q104157 ||' + NL +
'          ?admin1Type = wd:Q29946056' + NL +
'        )' + NL +
'      }' + NL +
'      OPTIONAL {' + NL +
'        ?admin1 wdt:P131 ?admin2 .' + NL +
'        OPTIONAL {' + NL +
'          ?admin2 wdt:P31 ?admin2Type .' + NL +
'          FILTER (' + NL +
'            ?admin2Type = wd:Q6256   ||' + NL +
'            ?admin2Type = wd:Q24698  ||' + NL +
'            ?admin2Type = wd:Q24746  ||' + NL +
'            ?admin2Type = wd:Q104157 ||' + NL +
'            ?admin2Type = wd:Q29946056' + NL +
'          )' + NL +
'        }' + NL +
'        OPTIONAL {' + NL +
'          ?admin2 wdt:P131 ?admin3 .' + NL +
'          OPTIONAL {' + NL +
'            ?admin3 wdt:P31 ?admin3Type .' + NL +
'            FILTER (' + NL +
'              ?admin3Type = wd:Q6256   ||' + NL +
'              ?admin3Type = wd:Q24698  ||' + NL +
'              ?admin3Type = wd:Q24746  ||' + NL +
'              ?admin3Type = wd:Q104157 ||' + NL +
'              ?admin3Type = wd:Q29946056' + NL +
'            )' + NL +
'          }' + NL +
'        }' + NL +
'      }' + NL +
'    }' + NL +
'  }' + NL +
'  OPTIONAL {' + NL +
'    ?marker wdt:P547 ?commemorates .' + NL +
'    OPTIONAL {' + NL +
'      ?commemoratesArticle schema:about ?commemorates ;' + NL +
'               schema:isPartOf <https://en.wikipedia.org/> .' + NL +
'    }' + NL +
'  }' + NL +
'  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }' + NL +
'}';
const SORT_MODES              = [
  { id: 'alpha', label: 'alphabetically'  },
  { id: 'qid',   label: 'by Wikidata QID' },
];

// Globals
var Markers = {};  // Hash to contain data about the historical markers
var CurrentSortModeIdx;
<commit_msg>Fix SPARQL query to account for unknown coordinates<commit_after>'use strict';

// Constants and fixed parameters
const BASE_TITLE = 'Historical Markers Map – Encyclopedia of Philippine Heritage';
const LANGUAGES = {
  'en'  : { name: 'English', qid: 'Q1860'  },
  'tl'  : { name: 'Tagalog', qid: 'Q34057' },
  'ceb' : { name: 'Cebuano', qid: 'Q33239' },
  'ilo' : { name: 'Ilocano', qid: 'Q35936' },
  'es'  : { name: 'Spanish', qid: 'Q1321'  },
  'de'  : { name: 'German' , qid: 'Q188'   },
  'fr'  : { name: 'French' , qid: 'Q150'   },
};
const ORDERED_LANGUAGES = ['en', 'tl', 'ceb', 'ilo', 'es', 'de', 'fr'];
const NL = '\n';
const SPARQL_QUERY =
'SELECT ?marker ?markerLabel ?coord ?title ?subtitle ?titleNoValue ?image' + NL +
'       ?date ?datePrecision ?inscription ?inscriptionNoValue' + NL +
'       ?country ?countryLabel ?locationLabel ?locationImage ?streetAddress' + NL +
'       ?admin0Label ?admin0Type ?admin1Label ?admin1Type' + NL +
'       ?admin2Label ?admin2Type ?admin3Label ?admin3Type' + NL +
'       ?vicinityImage ?vicinityDescription' + NL +
'       ?commemorates ?commemoratesLabel ?commemoratesArticle WHERE {' + NL +
'  ?marker wdt:P31 wd:Q21562164 ;' + NL +
'          wdt:P625 ?coord .' + NL +
'  FILTER (!isBLANK(?coord)) .' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P1476 ?titleStatement .' + NL +
'    OPTIONAL {' + NL +
'      ?titleStatement ps:P1476 ?title .' + NL +
'      OPTIONAL { ?titleStatement pq:P1680 ?subtitle }' + NL +
'    }' + NL +
'    OPTIONAL {' + NL +
'      ?titleStatement a ?titleNoValue .' + NL +
'      FILTER (?titleNoValue = wdno:P1476)' + NL +
'    }' + NL +
'  }' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P18 ?imageStatement .' + NL +
'    OPTIONAL {' + NL +
'      ?imageStatement ps:P18 ?image .' + NL +
'      FILTER NOT EXISTS { ?imageStatement pq:P3831 wd:Q16968816 }' + NL +
'    }' + NL +
'    OPTIONAL {' + NL +
'      ?imageStatement ps:P18 ?vicinityImage .' + NL +
'      OPTIONAL { ?imageStatement pq:P2096 ?vicinityDescription }' + NL +
'      FILTER EXISTS { ?imageStatement pq:P3831 wd:Q16968816 }' + NL +
'    }' + NL +
'  }' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P571 ?dateStatement .' + NL +
'    ?dateStatement psv:P571 ?dateValue .' + NL +
'    ?dateValue wikibase:timeValue ?date .' + NL +
'    ?dateValue wikibase:timePrecision ?datePrecision .' + NL +
'  }' + NL +
'  OPTIONAL { ?marker wdt:P1684 ?inscription }' + NL +
'  OPTIONAL {' + NL +
'    ?marker p:P1684 ?inscriptionStatement .' + NL +
'    ?inscriptionStatement a ?inscriptionNoValue .' + NL +
'    FILTER (?inscriptionNoValue = wdno:P1684)' + NL +
'  }' + NL +
'  OPTIONAL { ?marker wdt:P17 ?country }' + NL +
'  OPTIONAL {' + NL +
'    ?marker wdt:P276 ?location .' + NL +
'    OPTIONAL { ?location wdt:P18 ?locationImage }' + NL +
'  }' + NL +
'  OPTIONAL { ?marker wdt:P969 ?streetAddress }' + NL +
'  OPTIONAL {' + NL +
'    ?marker wdt:P131 ?admin0 .' + NL +
'    OPTIONAL {' + NL +
'      ?admin0 wdt:P31 ?admin0Type .' + NL +
'      FILTER (' + NL +
'        ?admin0Type = wd:Q6256   ||' + NL +
'        ?admin0Type = wd:Q24698  ||' + NL +
'        ?admin0Type = wd:Q24746  ||' + NL +
'        ?admin0Type = wd:Q104157 ||' + NL +
'        ?admin0Type = wd:Q29946056' + NL +
'      )' + NL +
'    }' + NL +
'    OPTIONAL {' + NL +
'      ?admin0 wdt:P131 ?admin1 .' + NL +
'      OPTIONAL {' + NL +
'        ?admin1 wdt:P31 ?admin1Type .' + NL +
'        FILTER (' + NL +
'          ?admin1Type = wd:Q6256   ||' + NL +
'          ?admin1Type = wd:Q24698  ||' + NL +
'          ?admin1Type = wd:Q24746  ||' + NL +
'          ?admin1Type = wd:Q104157 ||' + NL +
'          ?admin1Type = wd:Q29946056' + NL +
'        )' + NL +
'      }' + NL +
'      OPTIONAL {' + NL +
'        ?admin1 wdt:P131 ?admin2 .' + NL +
'        OPTIONAL {' + NL +
'          ?admin2 wdt:P31 ?admin2Type .' + NL +
'          FILTER (' + NL +
'            ?admin2Type = wd:Q6256   ||' + NL +
'            ?admin2Type = wd:Q24698  ||' + NL +
'            ?admin2Type = wd:Q24746  ||' + NL +
'            ?admin2Type = wd:Q104157 ||' + NL +
'            ?admin2Type = wd:Q29946056' + NL +
'          )' + NL +
'        }' + NL +
'        OPTIONAL {' + NL +
'          ?admin2 wdt:P131 ?admin3 .' + NL +
'          OPTIONAL {' + NL +
'            ?admin3 wdt:P31 ?admin3Type .' + NL +
'            FILTER (' + NL +
'              ?admin3Type = wd:Q6256   ||' + NL +
'              ?admin3Type = wd:Q24698  ||' + NL +
'              ?admin3Type = wd:Q24746  ||' + NL +
'              ?admin3Type = wd:Q104157 ||' + NL +
'              ?admin3Type = wd:Q29946056' + NL +
'            )' + NL +
'          }' + NL +
'        }' + NL +
'      }' + NL +
'    }' + NL +
'  }' + NL +
'  OPTIONAL {' + NL +
'    ?marker wdt:P547 ?commemorates .' + NL +
'    OPTIONAL {' + NL +
'      ?commemoratesArticle schema:about ?commemorates ;' + NL +
'               schema:isPartOf <https://en.wikipedia.org/> .' + NL +
'    }' + NL +
'  }' + NL +
'  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }' + NL +
'}';
const SORT_MODES              = [
  { id: 'alpha', label: 'alphabetically'  },
  { id: 'qid',   label: 'by Wikidata QID' },
];

// Globals
var Markers = {};  // Hash to contain data about the historical markers
var CurrentSortModeIdx;
<|endoftext|>


<commit_before>/*jslint unparam: true, browser: true, indent: 2 */

;(function ($, window, document, undefined) {
  'use strict';

  Foundation.libs.clearing = {
    name : 'clearing',

    version : '4.1.0',

    settings : {
      templates : {
        viewing : '×' +
          '
' +
          '

' +
          '
'
      },

      // comma delimited list of selectors that, on click, will close clearing,
      // add 'div.clearing-blackout, div.visible-img' to close on background click
      close_selectors : '.clearing-close',

      // event initializers and locks
      init : false,
      locked : false
    },

    init : function (method, options) {
      Foundation.inherit(this, 'set_data get_data remove_data throttle');

      if (typeof method === 'object') {
        options = $.extend(true, this.settings, method);
      }

      if (typeof method != 'string') {
        $(this.scope).find('ul[data-clearing]').each(function () {
          var self = Foundation.libs.clearing,
              $el = $(this),
              options = options || {},
              settings = self.get_data($el);

          if (!settings) {
            options.$parent = $el.parent();

            self.set_data($el, $.extend(true, self.settings, options));

            self.assemble($el.find('li'));

            if (!self.settings.init) {
              self.events().swipe_events();
            }
          }
        });

        return this.settings.init;
      } else {
        // fire method
        return this[method].call(this, options);
      }
    },

    // event binding and initial setup

    events : function () {
      var self = this;

      $(this.scope)
        .on('click.fndtn.clearing', 'ul[data-clearing] li',
          function (e, current, target) {
            var current = current || $(this),
                target = target || current,
                settings = self.get_data(current.parent());

            e.preventDefault();
            if (!settings) self.init();

            // set current and target to the clicked li if not otherwise defined.
            self.open($(e.target), current, target);
            self.update_paddles(target);
          })

        .on('click.fndtn.clearing', '.clearing-main-next',
          function (e) { this.nav(e, 'next') }.bind(this))
        .on('click.fndtn.clearing', '.clearing-main-prev',
          function (e) { this.nav(e, 'prev') }.bind(this))
        .on('click.fndtn.clearing', this.settings.close_selectors,
          function (e) { Foundation.libs.clearing.close(e, this) })
        .on('keydown.fndtn.clearing',
          function (e) { this.keydown(e) }.bind(this));

      $(window).on('resize.fndtn.clearing',
        function (e) { this.resize() }.bind(this));

      this.settings.init = true;
      return this;
    },

    swipe_events : function () {
      var self = this;

      $(this.scope)
        .on('touchstart.fndtn.clearing', '.visible-img', function(e) {
          if (!e.touches) { e = e.originalEvent; }
          var data = {
                start_page_x: e.touches[0].pageX,
                start_page_y: e.touches[0].pageY,
                start_time: (new Date()).getTime(),
                delta_x: 0,
                is_scrolling: undefined
              };

          $(this).data('swipe-transition', data);
          e.stopPropagation();
        })
        .on('touchmove.fndtn.clearing', '.visible-img', function(e) {
          if (!e.touches) { e = e.originalEvent; }
          // Ignore pinch/zoom events
          if(e.touches.length > 1 || e.scale && e.scale !== 1) return;

          var data = $(this).data('swipe-transition');

          if (typeof data === 'undefined') {
            data = {};
          }

          data.delta_x = e.touches[0].pageX - data.start_page_x;

          if ( typeof data.is_scrolling === 'undefined') {
            data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
          }

          if (!data.is_scrolling && !data.active) {
            e.preventDefault();
            var direction = (data.delta_x < 0) ? 'next' : 'prev';
            data.active = true;
            self.nav(e, direction);
          }
        })
        .on('touchend.fndtn.clearing', '.visible-img', function(e) {
          $(this).data('swipe-transition', {});
          e.stopPropagation();
        });
    },

    assemble : function ($li) {
      var $el = $li.parent(),
          settings = this.get_data($el),
          grid = $el.detach(),
          data = {
            grid: '
' + this.outerHTML(grid[0]) + '
',
            viewing: settings.templates.viewing
          },
          wrapper = '

' + data.viewing +
            data.grid + '

';

      return settings.$parent.append(wrapper);
    },

    // event callbacks

    open : function ($image, current, target) {
      var root = target.closest('.clearing-assembled'),
          container = root.find('div').first(),
          visible_image = container.find('.visible-img'),
          image = visible_image.find('img').not($image);

      if (!this.locked()) {
        // set the image to the selected thumbnail
        image.attr('src', this.load($image));

        this.loaded(image, function () {
          // toggle the gallery
          root.addClass('clearing-blackout');
          container.addClass('clearing-container');
          visible_image.show();
          this.fix_height(target)
            .caption(visible_image.find('.clearing-caption'), $image)
            .center(image)
            .shift(current, target, function () {
              target.siblings().removeClass('visible');
              target.addClass('visible');
            });
        }.bind(this));
      }
    },

    close : function (e, el) {
      e.preventDefault();

      var root = (function (target) {
            if (/blackout/.test(target.selector)) {
              return target;
            } else {
              return target.closest('.clearing-blackout');
            }
          }($(el))), container, visible_image;

      if (el === e.target && root) {
        container = root.find('div').first(),
        visible_image = container.find('.visible-img');
        this.settings.prev_index = 0;
        root.find('ul[data-clearing]')
          .attr('style', '').closest('.clearing-blackout')
          .removeClass('clearing-blackout');
        container.removeClass('clearing-container');
        visible_image.hide();
      }

      return false;
    },

    keydown : function (e) {
      var clearing = $('.clearing-blackout').find('ul[data-clearing]');

      if (e.which === 39) this.go(clearing, 'next');
      if (e.which === 37) this.go(clearing, 'prev');
      if (e.which === 27) $('a.clearing-close').trigger('click');
    },

    nav : function (e, direction) {
      var clearing = $('.clearing-blackout').find('ul[data-clearing]');

      e.preventDefault();
      this.go(clearing, direction);
    },

    resize : function () {
      var image = $('.clearing-blackout .visible-img').find('img');

      if (image.length) {
        this.center(image);
      }
    },

    // visual adjustments
    fix_height : function (target) {
      var lis = target.parent().children(),
          self = this;

      lis.each(function () {
          var li = $(this),
              image = li.find('img');

          if (li.height() > self.outerHeight(image)) {
            li.addClass('fix-height');
          }
        })
        .closest('ul')
        .width(lis.length * 100 + '%');

      return this;
    },

    update_paddles : function (target) {
      var visible_image = target
        .closest('.carousel')
        .siblings('.visible-img');

      if (target.next().length) {
        visible_image
          .find('.clearing-main-right')
          .removeClass('disabled');
      } else {
        visible_image
          .find('.clearing-main-right')
          .addClass('disabled');
      }

      if (target.prev().length) {
        visible_image
          .find('.clearing-main-prev')
          .removeClass('disabled');
      } else {
        visible_image
          .find('.clearing-main-prev')
          .addClass('disabled');
      }
    },

    center : function (target) {
      if (!this.rtl) {
        target.css({
          marginLeft : -(this.outerWidth(target) / 2),
          marginTop : -(this.outerHeight(target) / 2)
        });
      } else {
        target.css({
          marginRight : -(this.outerWidth(target) / 2),
          marginTop : -(this.outerHeight(target) / 2)
        });
      }
      return this;
    },

    // image loading and preloading

    load : function ($image) {
      var href = $image.parent().attr('href');

      this.preload($image);

      if (href) return href;
      return $image.attr('src');
    },

    preload : function ($image) {
      this
        .img($image.closest('li').next())
        .img($image.closest('li').prev());
    },

    loaded : function (image, callback) {
      // based on jquery.imageready.js
      // @weblinc, @jsantell, (c) 2012

      function loaded () {
        callback();
      }

      function bindLoad () {
        this.one('load', loaded);

        if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
          var src = this.attr( 'src' ),
              param = src.match( /\?/ ) ? '&' : '?';

          param += 'random=' + (new Date()).getTime();
          this.attr('src', src + param);
        }
      }

      if (!image.attr('src')) {
        loaded();
        return;
      }

      if (this.complete || this.readyState === 4) {
        loaded();
      } else {
        bindLoad.call(image);
      }
    },

    img : function (img) {
      if (img.length) {
        var new_img = new Image(),
            new_a = img.find('a');

        if (new_a.length) {
          new_img.src = new_a.attr('href');
        } else {
          new_img.src = img.find('img').attr('src');
        }
      }
      return this;
    },

    // image caption

    caption : function (container, $image) {
      var caption = $image.data('caption');

      if (caption) {
        container
          .text(caption)
          .show();
      } else {
        container
          .text('')
          .hide();
      }
      return this;
    },

    // directional methods

    go : function ($ul, direction) {
      var current = $ul.find('.visible'),
          target = current[direction]();

      if (target.length) {
        target
          .find('img')
          .trigger('click', [current, target]);
      }
    },

    shift : function (current, target, callback) {
      var clearing = target.parent(),
          old_index = this.settings.prev_index || target.index(),
          direction = this.direction(clearing, current, target),
          left = parseInt(clearing.css('left'), 10),
          width = this.outerWidth(target),
          skip_shift;

      // we use jQuery animate instead of CSS transitions because we
      // need a callback to unlock the next animation
      if (target.index() !== old_index && !/skip/.test(direction)){
        if (/left/.test(direction)) {
          this.lock();
          clearing.animate({left : left + width}, 300, this.unlock());
        } else if (/right/.test(direction)) {
          this.lock();
          clearing.animate({left : left - width}, 300, this.unlock());
        }
      } else if (/skip/.test(direction)) {
        // the target image is not adjacent to the current image, so
        // do we scroll right or not
        skip_shift = target.index() - this.settings.up_count;
        this.lock();

        if (skip_shift > 0) {
          clearing.animate({left : -(skip_shift * width)}, 300, this.unlock());
        } else {
          clearing.animate({left : 0}, 300, this.unlock());
        }
      }

      callback();
    },

    direction : function ($el, current, target) {
      var lis = $el.find('li'),
          li_width = this.outerWidth(lis) + (this.outerWidth(lis) / 4),
          up_count = Math.floor(this.outerWidth($('.clearing-container')) / li_width) - 1,
          target_index = lis.index(target),
          response;

      this.settings.up_count = up_count;

      if (this.adjacent(this.settings.prev_index, target_index)) {
        if ((target_index > up_count)
          && target_index > this.settings.prev_index) {
          response = 'right';
        } else if ((target_index > up_count - 1)
          && target_index <= this.settings.prev_index) {
          response = 'left';
        } else {
          response = false;
        }
      } else {
        response = 'skip';
      }

      this.settings.prev_index = target_index;

      return response;
    },

    adjacent : function (current_index, target_index) {
      for (var i = target_index + 1; i >= target_index - 1; i--) {
        if (i === current_index) return true;
      }
      return false;
    },

    // lock management

    lock : function () {
      this.settings.locked = true;
    },

    unlock : function () {
      this.settings.locked = false;
    },

    locked : function () {
      return this.settings.locked;
    },

    // plugin management/browser quirks

    outerHTML : function (el) {
      // support FireFox < 11
      return el.outerHTML || new XMLSerializer().serializeToString(el);
    },

    off : function () {
      $(this.scope).off('.fndtn.clearing');
      $(window).off('.fndtn.clearing');
      this.remove_data(); // empty settings cache
      this.settings.init = false;
    }
  };

}(Foundation.zj, this, this.document));
<commit_msg>Fire loaded event, even when image has already been loaded.<commit_after>/*jslint unparam: true, browser: true, indent: 2 */

;(function ($, window, document, undefined) {
  'use strict';

  Foundation.libs.clearing = {
    name : 'clearing',

    version : '4.1.0',

    settings : {
      templates : {
        viewing : '×' +
          '
' +
          '

' +
          '
'
      },

      // comma delimited list of selectors that, on click, will close clearing,
      // add 'div.clearing-blackout, div.visible-img' to close on background click
      close_selectors : '.clearing-close',

      // event initializers and locks
      init : false,
      locked : false
    },

    init : function (method, options) {
      Foundation.inherit(this, 'set_data get_data remove_data throttle');

      if (typeof method === 'object') {
        options = $.extend(true, this.settings, method);
      }

      if (typeof method != 'string') {
        $(this.scope).find('ul[data-clearing]').each(function () {
          var self = Foundation.libs.clearing,
              $el = $(this),
              options = options || {},
              settings = self.get_data($el);

          if (!settings) {
            options.$parent = $el.parent();

            self.set_data($el, $.extend(true, self.settings, options));

            self.assemble($el.find('li'));

            if (!self.settings.init) {
              self.events().swipe_events();
            }
          }
        });

        return this.settings.init;
      } else {
        // fire method
        return this[method].call(this, options);
      }
    },

    // event binding and initial setup

    events : function () {
      var self = this;

      $(this.scope)
        .on('click.fndtn.clearing', 'ul[data-clearing] li',
          function (e, current, target) {
            var current = current || $(this),
                target = target || current,
                settings = self.get_data(current.parent());

            e.preventDefault();
            if (!settings) self.init();

            // set current and target to the clicked li if not otherwise defined.
            self.open($(e.target), current, target);
            self.update_paddles(target);
          })

        .on('click.fndtn.clearing', '.clearing-main-next',
          function (e) { this.nav(e, 'next') }.bind(this))
        .on('click.fndtn.clearing', '.clearing-main-prev',
          function (e) { this.nav(e, 'prev') }.bind(this))
        .on('click.fndtn.clearing', this.settings.close_selectors,
          function (e) { Foundation.libs.clearing.close(e, this) })
        .on('keydown.fndtn.clearing',
          function (e) { this.keydown(e) }.bind(this));

      $(window).on('resize.fndtn.clearing',
        function (e) { this.resize() }.bind(this));

      this.settings.init = true;
      return this;
    },

    swipe_events : function () {
      var self = this;

      $(this.scope)
        .on('touchstart.fndtn.clearing', '.visible-img', function(e) {
          if (!e.touches) { e = e.originalEvent; }
          var data = {
                start_page_x: e.touches[0].pageX,
                start_page_y: e.touches[0].pageY,
                start_time: (new Date()).getTime(),
                delta_x: 0,
                is_scrolling: undefined
              };

          $(this).data('swipe-transition', data);
          e.stopPropagation();
        })
        .on('touchmove.fndtn.clearing', '.visible-img', function(e) {
          if (!e.touches) { e = e.originalEvent; }
          // Ignore pinch/zoom events
          if(e.touches.length > 1 || e.scale && e.scale !== 1) return;

          var data = $(this).data('swipe-transition');

          if (typeof data === 'undefined') {
            data = {};
          }

          data.delta_x = e.touches[0].pageX - data.start_page_x;

          if ( typeof data.is_scrolling === 'undefined') {
            data.is_scrolling = !!( data.is_scrolling || Math.abs(data.delta_x) < Math.abs(e.touches[0].pageY - data.start_page_y) );
          }

          if (!data.is_scrolling && !data.active) {
            e.preventDefault();
            var direction = (data.delta_x < 0) ? 'next' : 'prev';
            data.active = true;
            self.nav(e, direction);
          }
        })
        .on('touchend.fndtn.clearing', '.visible-img', function(e) {
          $(this).data('swipe-transition', {});
          e.stopPropagation();
        });
    },

    assemble : function ($li) {
      var $el = $li.parent(),
          settings = this.get_data($el),
          grid = $el.detach(),
          data = {
            grid: '
' + this.outerHTML(grid[0]) + '
',
            viewing: settings.templates.viewing
          },
          wrapper = '

' + data.viewing +
            data.grid + '

';

      return settings.$parent.append(wrapper);
    },

    // event callbacks

    open : function ($image, current, target) {
      var root = target.closest('.clearing-assembled'),
          container = root.find('div').first(),
          visible_image = container.find('.visible-img'),
          image = visible_image.find('img').not($image);

      if (!this.locked()) {
        // set the image to the selected thumbnail
        image.attr('src', this.load($image));

        this.loaded(image, function () {
          // toggle the gallery
          root.addClass('clearing-blackout');
          container.addClass('clearing-container');
          visible_image.show();
          this.fix_height(target)
            .caption(visible_image.find('.clearing-caption'), $image)
            .center(image)
            .shift(current, target, function () {
              target.siblings().removeClass('visible');
              target.addClass('visible');
            });
        }.bind(this));
      }
    },

    close : function (e, el) {
      e.preventDefault();

      var root = (function (target) {
            if (/blackout/.test(target.selector)) {
              return target;
            } else {
              return target.closest('.clearing-blackout');
            }
          }($(el))), container, visible_image;

      if (el === e.target && root) {
        container = root.find('div').first(),
        visible_image = container.find('.visible-img');
        this.settings.prev_index = 0;
        root.find('ul[data-clearing]')
          .attr('style', '').closest('.clearing-blackout')
          .removeClass('clearing-blackout');
        container.removeClass('clearing-container');
        visible_image.hide();
      }

      return false;
    },

    keydown : function (e) {
      var clearing = $('.clearing-blackout').find('ul[data-clearing]');

      if (e.which === 39) this.go(clearing, 'next');
      if (e.which === 37) this.go(clearing, 'prev');
      if (e.which === 27) $('a.clearing-close').trigger('click');
    },

    nav : function (e, direction) {
      var clearing = $('.clearing-blackout').find('ul[data-clearing]');

      e.preventDefault();
      this.go(clearing, direction);
    },

    resize : function () {
      var image = $('.clearing-blackout .visible-img').find('img');

      if (image.length) {
        this.center(image);
      }
    },

    // visual adjustments
    fix_height : function (target) {
      var lis = target.parent().children(),
          self = this;

      lis.each(function () {
          var li = $(this),
              image = li.find('img');

          if (li.height() > self.outerHeight(image)) {
            li.addClass('fix-height');
          }
        })
        .closest('ul')
        .width(lis.length * 100 + '%');

      return this;
    },

    update_paddles : function (target) {
      var visible_image = target
        .closest('.carousel')
        .siblings('.visible-img');

      if (target.next().length) {
        visible_image
          .find('.clearing-main-right')
          .removeClass('disabled');
      } else {
        visible_image
          .find('.clearing-main-right')
          .addClass('disabled');
      }

      if (target.prev().length) {
        visible_image
          .find('.clearing-main-prev')
          .removeClass('disabled');
      } else {
        visible_image
          .find('.clearing-main-prev')
          .addClass('disabled');
      }
    },

    center : function (target) {
      if (!this.rtl) {
        target.css({
          marginLeft : -(this.outerWidth(target) / 2),
          marginTop : -(this.outerHeight(target) / 2)
        });
      } else {
        target.css({
          marginRight : -(this.outerWidth(target) / 2),
          marginTop : -(this.outerHeight(target) / 2)
        });
      }
      return this;
    },

    // image loading and preloading

    load : function ($image) {
      var href = $image.parent().attr('href');

      this.preload($image);

      if (href) return href;
      return $image.attr('src');
    },

    preload : function ($image) {
      this
        .img($image.closest('li').next())
        .img($image.closest('li').prev());
    },

    loaded : function (image, callback) {
      // based on jquery.imageready.js
      // @weblinc, @jsantell, (c) 2012

      function loaded () {
        callback();
      }

      function bindLoad () {
        this.one('load', loaded);

        if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) {
          var src = this.attr( 'src' ),
              param = src.match( /\?/ ) ? '&' : '?';

          param += 'random=' + (new Date()).getTime();
          this.attr('src', src + param);
        }
      }

      if (!image.attr('src')) {
        loaded();
        return;
      }

      if (image[0].complete || image.readyState === 4) {
        loaded();
      } else {
        bindLoad.call(image);
      }
    },

    img : function (img) {
      if (img.length) {
        var new_img = new Image(),
            new_a = img.find('a');

        if (new_a.length) {
          new_img.src = new_a.attr('href');
        } else {
          new_img.src = img.find('img').attr('src');
        }
      }
      return this;
    },

    // image caption

    caption : function (container, $image) {
      var caption = $image.data('caption');

      if (caption) {
        container
          .text(caption)
          .show();
      } else {
        container
          .text('')
          .hide();
      }
      return this;
    },

    // directional methods

    go : function ($ul, direction) {
      var current = $ul.find('.visible'),
          target = current[direction]();

      if (target.length) {
        target
          .find('img')
          .trigger('click', [current, target]);
      }
    },

    shift : function (current, target, callback) {
      var clearing = target.parent(),
          old_index = this.settings.prev_index || target.index(),
          direction = this.direction(clearing, current, target),
          left = parseInt(clearing.css('left'), 10),
          width = this.outerWidth(target),
          skip_shift;

      // we use jQuery animate instead of CSS transitions because we
      // need a callback to unlock the next animation
      if (!/skip/.test(direction)){
        if (/left/.test(direction)) {
          this.lock();
          clearing.animate({left : left + width}, 300, this.unlock());
        } else if (/right/.test(direction)) {
          this.lock();
          clearing.animate({left : left - width}, 300, this.unlock());
        }
      } else if (/skip/.test(direction)) {
        // the target image is not adjacent to the current image, so
        // do we scroll right or not
        skip_shift = target.index() - this.settings.up_count;
        this.lock();

        if (skip_shift > 0) {
          clearing.animate({left : -(skip_shift * width)}, 300, this.unlock());
        } else {
          clearing.animate({left : 0}, 300, this.unlock());
        }
      }

      callback();
    },

    direction : function ($el, current, target) {
      var lis = $el.find('li'),
          li_width = this.outerWidth(lis) + (this.outerWidth(lis) / 4),
          up_count = Math.floor(this.outerWidth($('.clearing-container')) / li_width) - 1,
          target_index = lis.index(target),
          response;

      this.settings.up_count = up_count;

      if (this.adjacent(this.settings.prev_index, target_index)) {
        if ((target_index > up_count)
          && target_index > this.settings.prev_index) {
          response = 'right';
        } else if ((target_index > up_count - 1)
          && target_index <= this.settings.prev_index) {
          response = 'left';
        } else {
          response = false;
        }
      } else {
        response = 'skip';
      }

      this.settings.prev_index = target_index;

      return response;
    },

    adjacent : function (current_index, target_index) {
      for (var i = target_index + 1; i >= target_index - 1; i--) {
        if (i === current_index) return true;
      }
      return false;
    },

    // lock management

    lock : function () {
      this.settings.locked = true;
    },

    unlock : function () {
      this.settings.locked = false;
    },

    locked : function () {
      return this.settings.locked;
    },

    // plugin management/browser quirks

    outerHTML : function (el) {
      // support FireFox < 11
      return el.outerHTML || new XMLSerializer().serializeToString(el);
    },

    off : function () {
      $(this.scope).off('.fndtn.clearing');
      $(window).off('.fndtn.clearing');
      this.remove_data(); // empty settings cache
      this.settings.init = false;
    }
  };

}(Foundation.zj, this, this.document));
<|endoftext|>


<commit_before>function PointDefenseDrone (resources, overrides) {
  Entity.call(this, resources, overrides);
  this.width = 32;
  this.height = 32;

  this.shadow.on = true;
  this.shadow.size = { x: 4, y: 4 };
  this.shadow.shape = 'circle';

  this.sounds = { build: 'beep' };
  this.game.audio.play(this.sounds.build, 0.9);

  this.alignment = 'friendly';
  this.friendlyPierceChance = 1;
  this.enemyPierceChance = 0;

  this.orbitRadius = 64;
  this.angularVelocity = 2;

  this.weapon = new MachineGun(this, { bulletLifespan: 5, damage: 0.5, fireRate: 2, recoil: false, volume: 0.1 });
  this.weapon.sounds.fire = 'shoot1';
  this.deferSource = this.game.player;

  this.target = null;
}

PointDefenseDrone.prototype = new Entity();

PointDefenseDrone.prototype.constructor = PointDefenseDrone;

PointDefenseDrone.prototype.tick = function () {
  var rad = Util.deg2rad(this.age % 360) * this.angularVelocity;
  this.x = this.game.player.x + -Math.cos(rad) * this.orbitRadius;
  this.y = this.game.player.y + Math.sin(rad) * this.orbitRadius;
  this.rotation = rad;

  if (this.age % 2 === 0) {
    if (Util.isDefined(this.game.player.nearestEnemy) &&
        this.game.player.distanceToNearestEnemy < 200 &&
        !this.game.player.nearestEnemy.markedForDeletion)
      this.weapon.fireAt(this.game.player.nearestEnemy);
  }
};

PointDefenseDrone.prototype.getImage = function () {
  return this.sprites.flash1;
};<commit_msg>Fix PDD having recoil.<commit_after>function PointDefenseDrone (resources, overrides) {
  Entity.call(this, resources, overrides);
  this.width = 32;
  this.height = 32;

  this.shadow.on = true;
  this.shadow.size = { x: 4, y: 4 };
  this.shadow.shape = 'circle';

  this.sounds = { build: 'beep' };
  this.game.audio.play(this.sounds.build, 0.9);

  this.alignment = 'friendly';
  this.friendlyPierceChance = 1;
  this.enemyPierceChance = 0;

  this.orbitRadius = 64;
  this.angularVelocity = 2;

  this.weapon = new MachineGun(this, { bulletLifespan: 5, damage: 0.5, fireRate: 2, recoilMultiplier: 0, volume: 0.1 });
  this.weapon.sounds.fire = 'shoot1';
  this.deferSource = this.game.player;

  this.target = null;
}

PointDefenseDrone.prototype = new Entity();

PointDefenseDrone.prototype.constructor = PointDefenseDrone;

PointDefenseDrone.prototype.tick = function () {
  var rad = Util.deg2rad(this.age % 360) * this.angularVelocity;
  this.x = this.game.player.x + -Math.cos(rad) * this.orbitRadius;
  this.y = this.game.player.y + Math.sin(rad) * this.orbitRadius;
  this.rotation = rad;

  if (this.age % 2 === 0) {
    if (Util.isDefined(this.game.player.nearestEnemy) &&
        this.game.player.distanceToNearestEnemy < 200 &&
        !this.game.player.nearestEnemy.markedForDeletion)
      this.weapon.fireAt(this.game.player.nearestEnemy);
  }
};

PointDefenseDrone.prototype.getImage = function () {
  return this.sprites.flash1;
};<|endoftext|>


<commit_before>/**Subclass of Property that adds methods specific to boolean values*/
define( ['phetcommon/model/property/Property', 'util/Inheritance'], function ( Property, Inheritance ) {

    Inheritance.inheritPrototype( BooleanProperty, Property );

    function BooleanProperty( value ) {Property.call( this, value );}

    BooleanProperty.prototype.toggle = function () {this.set( !this.get() );};

    return BooleanProperty;
} );<commit_msg>add missing copyright and author<commit_after>// Copyright 2002-2013, University of Colorado

/**
 * Subclass of Property that adds methods specific to boolean values
 *
 * @author Sam Reid
 */
define( ['phetcommon/model/property/Property', 'util/Inheritance'], function ( Property, Inheritance ) {

    Inheritance.inheritPrototype( BooleanProperty, Property );

    function BooleanProperty( value ) {Property.call( this, value );}

    BooleanProperty.prototype.toggle = function () {this.set( !this.get() );};

    return BooleanProperty;
} );<|endoftext|>


<commit_before>/*
 * This script is bootstrapped by the bookmarklet gaget code.
 */

javascript:(function() {

	var head = document.getElementsByTagName('head')[0];

	var pollRetries = 10;
	var pollWait = 100;

	var versionToUse = "trunk";
	/*var versionToUse = "tags/0.6"; */

	var svnRoot = "http://ufd.googlecode.com/svn/" + versionToUse;
	var googRoot = "http://ajax.googleapis.com/ajax/libs";

	var cssLoaded = false;
	getCSS(svnRoot + "/css/ufd-base.css");
	getCSS(svnRoot + "/css/plain/plain.css");

	var itemCount = 3;
	getScript(googRoot + "/jquery/1.4.2/jquery.min.js");
	getScript(googRoot + "/jqueryui/1.7.2/jquery-ui.min.js");
	getScript(svnRoot + "/src/jquery.ui.ufd.js");

	/* helpers */

	function getCSS(url) {
		var css = document.createElement('LINK');
		css.rel = 'stylesheet';
		css.type = 'text/css';
		css.media = 'screen';
		css.href = url;
		head.appendChild(css);
	}

	function getScript(url) {
		var script = document.createElement('script');
		script.src = url;
		script.type = 'text/javascript';
		script.onload = script.onreadystatechange = load;
		head.appendChild(script);
	}

	function load() {
		if ((!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') && !this.visited) {
			this.visited = true;
			if(--itemCount) return; /* haven't loaded all yet. */

			setTimeout(poll, 1); /* straight away first time */
		}
	}

	function poll() {
		if(!cssLoaded) { /* chck if both css has loaded */
			var base = false, plain = false;
			var ss = document.styleSheets;
			for (var i = 0; i < ss.length; i++) {
			    var url = ss[i].href || "";
			    base = base || (url.search("ufd-base.css") > 0);
			    plain = plain || (url.search("plain.css") > 0);
			}
			cssLoaded = (base && plain);
		}

		if (cssLoaded == true &&
			typeof jQuery != 'undefined' &&
			typeof jQuery.ui != 'undefined' &&
			typeof jQuery.ui.ufd != 'undefined' ) {

			/* don't re-wrap existing ufds! */
			jQuery(":not(span.ufd) > select:not([multiple])").ufd({addEmphasis: true});
			jQuery.noConflict(true); 	/* the injected jquery, ui and ufd no longer are available via window.jQuery or window.$ */

		} else if(--pollRetries) {
			setTimeout(poll, pollWait);

		} else {
			alert("Sorry, UFD didn't manage to initalize properly.");
		}
	}
})();

<commit_msg><commit_after>/*
 * This script is bootstrapped by the bookmarklet gaget code.
 */

javascript:(function() {

	var head = document.getElementsByTagName('head')[0];

	var pollRetries = 10;
	var pollWait = 200;

	var versionToUse = "trunk";
	/*var versionToUse = "tags/0.6"; */

	var svnRoot = "http://ufd.googlecode.com/svn/" + versionToUse;
	var googRoot = "http://ajax.googleapis.com/ajax/libs";

	var cssLoaded = false;
	getCSS(svnRoot + "/css/ufd-base.css");
	getCSS(svnRoot + "/css/plain/plain.css");

	var itemCount = 3;
	getScript(googRoot + "/jquery/1.4.2/jquery.min.js");
	getScript(googRoot + "/jqueryui/1.7.2/jquery-ui.min.js");
	getScript(svnRoot + "/src/jquery.ui.ufd.js");

	/* helpers */

	function getCSS(url) {
		var css = document.createElement('LINK');
		css.rel = 'stylesheet';
		css.type = 'text/css';
		css.media = 'screen';
		css.href = url;
		head.appendChild(css);
	}

	function getScript(url) {
		var script = document.createElement('script');
		script.src = url;
		script.type = 'text/javascript';
		script.onload = script.onreadystatechange = load;
		head.appendChild(script);
	}

	function load() {
		if ((!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') && !this.visited) {
			this.visited = true;
			if(--itemCount) return; /* haven't loaded all yet. */

			setTimeout(poll, 1); /* straight away first time */
		}
	}

	function poll() {
		if(!cssLoaded) { /* chck if both css has loaded */
			var base = false, plain = false;
			var ss = document.styleSheets;
			for (var i = 0; i < ss.length; i++) {
			    var url = ss[i].href || "";
			    base = base || (url.search("ufd-base.css") > 0);
			    plain = plain || (url.search("plain.css") > 0);
			}
			cssLoaded = (base && plain);
		}

		if (cssLoaded == true &&
			typeof jQuery != 'undefined' &&
			typeof jQuery.ui != 'undefined' &&
			typeof jQuery.ui.ufd != 'undefined' ) {
			alert("damn you ie");
			/* don't re-wrap existing ufds! */
			jQuery(":not(span.ufd) > select:not([multiple])").ufd({addEmphasis: true});
			jQuery.noConflict(true); 	/* the injected jquery, ui and ufd no longer are available via window.jQuery or window.$ */

		} else if(--pollRetries) {
			setTimeout(poll, pollWait);

		} else {
			alert("Sorry, UFD didn't manage to initalize properly.");
		}
	}
})();

<|endoftext|>


<commit_before>/*

    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      This file is part of the Smart Developer Hub Project:
        http://www.smartdeveloperhub.org/
      Center for Open Middleware
            http://www.centeropenmiddleware.com/
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Copyright (C) 2015 Center for Open Middleware.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      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.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
*/

'use strict';

exports.timeBasedDataList = function(callback) {

    callback(tbd.tbd);
};

exports.getTimeBasedData = function(tid, rid, uid, from, to, callback) {
    var acum = 0;

    // Normalice parameters
    if (!(tid in tbdById)) {
        console.log("TID not found");
        callback(404);
        return;
    }

    if (tbdById[tid].params.indexOf('uid') >= 0) {
        // uid required for this metric
        if (typeof uid == 'undefined') {
            console.log(tid + " metric require query param 'uid' ");
            callback();
            return;
        } else if (!(uid in usersById)) {
            console.log("UID not found: " + uid);
            callback(404);
            return;
        }
    } else if (typeof uid !== 'undefined') {
        console.log(tid + " metric does not require query param 'uid'");
        uid = null;
    }

    if (tbdById[tid].params.indexOf('rid') >= 0) {
        // rid required for this metric
        if (typeof rid == 'undefined') {
            console.log(tid + " metric require query param 'rid'");
            callback();
            return;
        } else if (!(rid in repositoriesById)) {
            console.log("RID not found: " + uid);
            callback(404);
            return;
        }
    } else if (typeof rid !== 'undefined') {
        console.log(tid + " metric does not require query param 'rid'");
        rid = null;
    }

    if (tbdById[tid].params.indexOf('from') >= 0) {
        // from date parameter required for this metric
        if (typeof from == 'undefined') {
            console.log(tid + " metric require query param 'from'");
            callback();
            return;
        }
    } else if (typeof from == 'undefined') {
        from = defaultDateRange.from;
    }

    if (tbdById[tid].params.indexOf('to') >= 0) {
        // to date parameter required for this metric
        if (typeof to == 'undefined') {
            console.log(tid + " metric require query param 'to'");
            callback();
            return;
        }
    } else if (typeof to == 'undefined') {
        to = defaultDateRange.to;
    }
    // Dates in ms
    from = from.getTime();
    to = to.getTime();

    var localcallback = function(thetbd) {
        var result = {
            "values" : thetbd.data,
            "interval" : {
                "from" : from,
                "to" : to
            },
            "tbdinfo" : tbdById[tid],
            "timestamp" : thetbd.timestamp
        };
        callback(result);
    };

    sdhWrapper.getTBDValue(tid, rid, uid, from, to, localcallback);

};
<commit_msg>Fix bugs in tbd controller<commit_after>/*

    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      This file is part of the Smart Developer Hub Project:
        http://www.smartdeveloperhub.org/
      Center for Open Middleware
            http://www.centeropenmiddleware.com/
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      Copyright (C) 2015 Center for Open Middleware.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
      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.
    #-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
*/

'use strict';

exports.timeBasedDataList = function(callback) {

    callback(tbd.tbd);
};

exports.getTimeBasedData = function(tid, rid, uid, from, to, callback) {

    var tbdRequest = function tbdRequest () {
        // Normalize params
        if (!uidRequired && typeof uid !== 'undefined') {
            console.log(tid + " time-based data does not require query param 'uid'");
            uid = null;
        }
        if (!ridRequired && typeof rid !== 'undefined') {
            console.log(tid + " time-based data does not require query param 'rid'");
            rid = null;
        }

        // Date Range
        if (typeof from == 'undefined') {
            from = defaultDateRange.from;
        }
        if (typeof to == 'undefined') {
            to = defaultDateRange.to;
        }
        // Dates in ms
        from = from.getTime();
        to = to.getTime();

        var localcallback2 = function(thetbd) {
            var result = {
                "values" : thetbd.data,
                "interval" : {
                    "from" : from,
                    "to" : to
                },
                "tbdinfo" : tbdById[tid],
                "timestamp" : thetbd.timestamp
            };
            callback(result);
        };
        sdhWrapper.getTBDValue(tid, rid, uid, from, to, localcallback2);
    };

    // check ids
    if (!(tid in tbdById)) {
        console.error("TID not found: " + tid);
        callback(404);
        return;
    }

    var uidRequired = tbdById[tid].params.indexOf('uid') >= 0;
    var ridRequired = tbdById[tid].params.indexOf('rid') >= 0;

    if (uidRequired && ridRequired) {
        // uid and rid required for this tbd
        if (typeof uid == 'undefined') {
            console.error(tid + " time-based data require query param 'uid'");
            callback(400);
            return;
        }
        if (typeof rid == 'undefined') {
            console.error(tid + " time-based data require query param 'rid'");
            callback(400);
            return;
        }
        sdhWrapper.userExist(uid, function(usExist) {
            if (!usExist) {
                console.error("UID not found: " + uid);
                callback(404);
            } else {
                sdhWrapper.repoExist(rid, function(reExist) {
                    if (!reExist) {
                        console.error("RID not found: " + rid);
                        callback(404);
                    } else {
                        // continue with the tbd
                        tbdRequest();
                    }
                    return;
                });
            }
            return;
        });
        return;
    } else if (uidRequired) {
        // only uid required for this tbd
        if (typeof uid == 'undefined') {
            console.error(tid + " time-based data require query param 'uid'");
            callback(400);
            return;
        } else {
            sdhWrapper.userExist(uid, function(usExist) {
                if (!usExist) {
                    console.error("UID not found: " + uid);
                    callback(404);
                } else {
                    // continue with the tbd
                    tbdRequest();
                }
                return;
            });
        }
        return;
    } else if (ridRequired) {
        // only rid required for this tbd
        if (typeof rid == 'undefined') {
            console.log(tid + " time-based data require query param 'rid'");
            callback(400);
            return;
        } else {
            sdhWrapper.repoExist(rid, function(reExist) {
                if (!reExist) {
                    console.log("RID not found: " + rid);
                    callback(404);
                } else {
                    // continue with the tbd
                    tbdRequest();
                }
                return;
            });
        }
        return;
    } else {
        // no one id is required
        tbdRequest();
    }
};
<|endoftext|>


<commit_before>const webpack = require('webpack')
const merge = require('webpack-merge')
const base = require('./webpack.base.config')
const vueConfig = require('./vue-loader.config')
const HTMLPlugin = require('html-webpack-plugin')
const SWPrecachePlugin = require('sw-precache-webpack-plugin')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const path = require('path')

const config = merge(base, {
  resolve: {
    alias: {
      'create-api': './create-api-client.js'
    }
  },
  plugins: [
    // strip dev-only code in Vue source
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
      'process.env.VUE_ENV': '"client"'
    }),
    // extract vendor chunks for better caching
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor'
    }),
    // generate output HTML
    new HTMLPlugin({
      template: 'src/index.template.html'
    })
  ]
})

if (process.env.NODE_ENV === 'production') {
  config.plugins.push(
    // minify JS
    new UglifyJSPlugin(),
    // auto generate service worker
    new SWPrecachePlugin({
      cacheId: 'vue-sfr',
      filename: 'service-worker.js',
      staticFileGlobsIgnorePatterns: [/\.map$/],
      staticFileGlobs: [
        'dist/**.*',
        'assets/**.*',
        'assets/ig/**.*',
        'index.html',
        '/'
      ],
      runtimeCaching: [
        {
          urlPattern: "^https://fonts\.googleapis\.com/", /** cache the html stub  */
          handler: "cacheFirst"
        },
        {
          urlPattern: "^https://fonts\.gstatic\.com/", /** cache the html stub  */
          handler: "cacheFirst"
        },
        {
          urlPattern: "^https://unpkg\.com/", /** cache the html stub  */
          handler: "cacheFirst"
        },
        {
        urlPattern: "/pwa.html", /** cache the html stub  */
        handler: "fastest"
      },{
        urlPattern: "^/$", /** cache the html stub for homepage  */
        handler: "fastest"
      },
      {
        urlPattern: "/p/*", /** cache the html stub  */
        handler: "fastest"
      },
      {
        urlPattern: "/c/*", /** cache the html stub  */
        handler: "fastest"
      },
      {
        urlPattern: "/img/(.*)",
        handler: "fastest"
      },{
        urlPattern: "/api/catalog/*",
        handler: "fastest"
      },{
        urlPattern: "/api/*",
        handler: "networkFirst"
      },{
        urlPattern: "/assets/logo.svg",
        handler: "networkFirst"
      },{
        urlPattern: "/index.html",
        handler: "fastest"
      },{
        urlPattern: "/assets/*",
        handler: "networkFirst"
      },{
        urlPattern: "/assets/ig/(.*)",
        handler: "networkFirst"
      },{
        urlPattern: "/dist/(.*)",
        handler: "fastest"
      }],
      "importScripts": ['/service-worker-ext.js'] /* custom logic */
    })
  )
}

const configSW = merge({}, base); // this is basicaly a work-around to compile the service workers extensions as they are not included nowhere but in service worker only
const themeRoot = require('./theme-path')

configSW.entry =  {
  'service-worker-ext': themeRoot + '/service-worker-ext.js',
}
configSW.output =  {
  path: path.resolve(__dirname, '../../dist'),
  publicPath: '/dist/',
  filename: '[name].js'
},

module.exports = [config, configSW];
<commit_msg>SW fine tune<commit_after>const webpack = require('webpack')
const merge = require('webpack-merge')
const base = require('./webpack.base.config')
const vueConfig = require('./vue-loader.config')
const HTMLPlugin = require('html-webpack-plugin')
const SWPrecachePlugin = require('sw-precache-webpack-plugin')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const path = require('path')

const config = merge(base, {
  resolve: {
    alias: {
      'create-api': './create-api-client.js'
    }
  },
  plugins: [
    // strip dev-only code in Vue source
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
      'process.env.VUE_ENV': '"client"'
    }),
    // extract vendor chunks for better caching
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor'
    }),
    // generate output HTML
    new HTMLPlugin({
      template: 'src/index.template.html'
    })
  ]
})

if (process.env.NODE_ENV === 'production') {
  config.plugins.push(
    // minify JS
    new UglifyJSPlugin(),
    // auto generate service worker
    new SWPrecachePlugin({
      cacheId: 'vue-sfr',
      filename: 'service-worker.js',
      staticFileGlobsIgnorePatterns: [/\.map$/],
      staticFileGlobs: [
        'dist/**.*',
        'assets/**.*',
        'assets/ig/**.*',
        'index.html',
        '/'
      ],
      runtimeCaching: [
        {
          urlPattern: "^https://fonts\.googleapis\.com/", /** cache the html stub  */
          handler: "cacheFirst"
        },
        {
          urlPattern: "^https://fonts\.gstatic\.com/", /** cache the html stub  */
          handler: "cacheFirst"
        },
        {
          urlPattern: "^https://unpkg\.com/", /** cache the html stub  */
          handler: "cacheFirst"
        },
        {
        urlPattern: "/pwa.html", /** cache the html stub  */
        handler: "fastest"
      },{
        urlPattern: "/", /** cache the html stub for homepage  */
        handler: "fastest"
      },
      {
        urlPattern: "/p/*", /** cache the html stub  */
        handler: "fastest"
      },
      {
        urlPattern: "/c/*", /** cache the html stub  */
        handler: "fastest"
      },
      {
        urlPattern: "/img/(.*)",
        handler: "fastest"
      },{
        urlPattern: "/api/catalog/*",
        handler: "fastest"
      },{
        urlPattern: "/api/*",
        handler: "networkFirst"
      },{
        urlPattern: "/assets/logo.svg",
        handler: "networkFirst"
      },{
        urlPattern: "/index.html",
        handler: "fastest"
      },{
        urlPattern: "/assets/*",
        handler: "fastest"
      },{
        urlPattern: "/assets/ig/(.*)",
        handler: "fastest"
      },{
        urlPattern: "/dist/(.*)",
        handler: "fastest"
      }],
      "importScripts": ['/service-worker-ext.js'] /* custom logic */
    })
  )
}

const configSW = merge({}, base); // this is basicaly a work-around to compile the service workers extensions as they are not included nowhere but in service worker only
const themeRoot = require('./theme-path')

configSW.entry =  {
  'service-worker-ext': themeRoot + '/service-worker-ext.js',
}
configSW.output =  {
  path: path.resolve(__dirname, '../../dist'),
  publicPath: '/dist/',
  filename: '[name].js'
},

module.exports = [config, configSW];
<|endoftext|>


<commit_before>import HomeRoute from 'routes/Home'

describe('(Route) Home', () => {
  let _component

  beforeEach(() => {
    _component = HomeRoute.component()
  })

  it('Should return a route configuration object', () => {
    expect(typeof(HomeRoute)).to.equal('object')
  })

  it('Should define a route component', () => {
    expect(_component.type).to.equal('div')
  })
})
<commit_msg>Update Home Route index test<commit_after>import HomeRoute from 'routes/Home'

describe('(Route) Home', () => {
  let _component

  beforeEach(() => {
    _component = HomeRoute.component()
  })

  it('Should return a route configuration object', () => {
    expect(typeof(HomeRoute)).to.equal('object')
  })

  it('Should define a route component', () => {
    expect(_component.type).to.equal('section')
  })
})
<|endoftext|>


<commit_before>define(['js/svg/SvgElement'], function(SvgElement) {

    return SvgElement.inherit("sprd.view.svg.ConfigurationRenderer", {
        defaults: {
            x: 0,
            y: 0,
            width: "{configuration.size().width}",
            height: "{configuration.size().height}",
            focused: "{configurationViewer.focused}",

            imageService: null
        },

        $classAttributes: ["configuration","productViewer", "configurationViewer","textArea","showSelection","focused", "imageService"],

        _focus: function() {
            // hook: invoked after configuration viewer move, scale, rotate finished
        }
    })
});<commit_msg>added configuration-renderer class<commit_after>define(['js/svg/SvgElement'], function(SvgElement) {

    return SvgElement.inherit("sprd.view.svg.ConfigurationRenderer", {
        defaults: {
            x: 0,
            y: 0,
            width: "{configuration.size().width}",
            height: "{configuration.size().height}",
            focused: "{configurationViewer.focused}",
            componentClass: "configuration-renderer",

            imageService: null
        },

        $classAttributes: ["configuration","productViewer", "configurationViewer","textArea","showSelection","focused", "imageService"],

        _focus: function() {
            // hook: invoked after configuration viewer move, scale, rotate finished
        }
    })
});<|endoftext|>