diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..f1066ea6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +/.idea/ diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..071272d9 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,12 @@ +{ + "node": true, + "browser": true, + "bitwise": true, + "undef": true, + "trailing": true, + "quotmark": true, + "indent": 4, + "unused": "vars", + "latedef": "nofunc", + "-W030": false +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..5db520c8 --- /dev/null +++ b/LICENSE @@ -0,0 +1,25 @@ +Tools for Apache Cordova CLI - Plugin Simulation + +Copyright (c) Microsoft Corporation + +All rights reserved. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/NOTICE b/NOTICE new file mode 100644 index 00000000..c5040192 --- /dev/null +++ b/NOTICE @@ -0,0 +1,85 @@ +Tools for Apache Cordova CLI - Plugin Simulation - Third Party Notices + +'Tools for Apache Cordova CLI - Plugin Simulation' is based on or incorporates +material and code from the projects listed below (collectively "Third Party +Code"). Microsoft is not the original author of the Third Party Code. The +original copyright notice and the license, under which Microsoft received such +Third Party Code, are set forth below. Such license and notices are provided +for informational purposes only. + +Microsoft licenses the Third Party Code to you under the terms of the MIT +License. All Third Party Code licensed by Microsoft under the MIT License (the +"License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at https://opensource.org/licenses/MIT + +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. + +See the MIT License for specific language governing permissions and limitations +under the License. + +------------------------------------------------------------------------------- +Third Party Code Components +------------------------------------------------------------------------------- + +-- Apache Ripple -------------------------------------------------------------- + +Contains code based on code from Apache Ripple +http://ripple.incubator.apache.org/ +https://github.com/apache/incubator-ripple +Released under Apache 2.0 License. + +-- Wii Opera SDK -------------------------------------------------------------- + +3D Math Class v2.7.22 2008-12-14 +(c) 2007-2008 Daniel Gump. All Rights Reserved. +(see src/plugins/cordova-plugin-device-motion/3d.js) + +Drawing Class v2.6.16 2008-12-14 * +(c) 2007-2008 Daniel Gump. All Rights Reserved +(see src/plugins/cordova-plugin-device-motion/draw.js) + +http://wiioperasdk.com, http://hullbreachonline.com +hullbreach@hullbreachonline.com + +-- OpenLayers Map Viewer Library ---------------------------------------------- + +OpenLayers.js -- OpenLayers Map Viewer Library +Copyright (c) 2006-2013 by OpenLayers Contributors +Published under the 2-clause BSD license. +See http://openlayers.org/dev/license.txt for the full text of the license, +and http://openlayers.org/dev/authors.txt for full list of contributors. +(see src/plugins/cordova-plugin-geolocation/OpenLayers.js) + +Includes compressed code under the following licenses: + + XMLHttpRequest.js + Copyright (C) 2010 Sergey Ilinsky (http://www.ilinsky.com) + Released under Apache License, Version 2.0 with the permission of the author: + https://github.com/openlayers/openlayers/blob/release-2.12/lib/OpenLayers/Request/XMLHttpRequest.js + + OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is + Copyright (c) 2006, Yahoo! Inc. + All rights reserved. + + Contains portions of Rico + Copyright 2005 Sabre Airline Solutions + Licensed under the Apache License, Version 2.0 (the "License"); + +-- moment.js ------------------------------------------------------------------ + +moment.js +version : 2.8.4 +authors : Tim Wood, Iskren Chernev, Moment.js contributors +license : MIT +momentjs.com +(see src/plugins/cordova-plugin-globalization/moment.js) + +-- jQuery JavaScript Library -------------------------------------------------- + +jQuery v2.1.4 +Copyright 2005, 2015 jQuery Foundation, Inc. +Licensed under MIT +http://jquery.org/license +(see src/third-party/jquery.min.js) diff --git a/README.md b/README.md new file mode 100644 index 00000000..0a2c6d8f --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +Server and app host support for taco-simulate. + +# Installation + +``` +npm install taco-simulator-server +``` diff --git a/RELEASENOTES.md b/RELEASENOTES.md new file mode 100644 index 00000000..ab0a0e25 --- /dev/null +++ b/RELEASENOTES.md @@ -0,0 +1,4 @@ +# taco-simulate-server Release Notes + +### 0.1.0 (Oct 8, 2015) +* Initial test release diff --git a/docs/gpx.md b/docs/gpx.md new file mode 100644 index 00000000..379fddeb --- /dev/null +++ b/docs/gpx.md @@ -0,0 +1,9 @@ +GPX is a platform-independent serialization schema that we use to simulate geolocation routes. +There are several ways you can generate GPX files. Here are three examples: + +1. Record an actual route using the [*Endomondo* mobile app](http://endomondo.com). After you have + recorded the route, log into the *Endomondo* site and download the route as a GPX file using the + export feature in the RH navigation pane. +2. Create a route by requesting driving directions at http://yournavigation.org. Select the `Export` + feature and select GPX format +3. If you prefer Google maps, follow these instructions: http://www.elsewhere.org/journal/gmaptogpx/. diff --git a/package.json b/package.json new file mode 100644 index 00000000..7d6e56d2 --- /dev/null +++ b/package.json @@ -0,0 +1,46 @@ +{ + "name": "taco-simulate-server", + "version": "0.1.0", + "description": "Server and app host module for taco-simulate (Cordova plugin simulation).", + "main": "src/server.js", + "scripts": { + "prepublish": "in-install || npm shrinkwrap", + "postpublish": "rimraf npm-shrinkwrap.json" + }, + "repository": { + "type": "git", + "url": "https://github.com/microsoft/taco-simulator-server" + }, + "keywords": [ + "taco", + "cordova", + "plugins", + "simulation" + ], + "author": { + "name": "Microsoft Corp." + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/microsoft/taco-simulator-server/issues" + }, + "homepage": "https://github.com/microsoft/taco-simulator-server", + "engines": { + "node": ">= 0.12.0", + "npm": ">= 2.5.1" + }, + "dependencies": { + "browserify": "^11.2.0", + "chalk": "^1.1.1", + "cordova-serve": "^1.0.0", + "q": "^1.4.1", + "replacestream": "^4.0.0", + "send": "timbarham/send#transform", + "socket.io": "^1.3.7", + "through2": "^2.0.0" + }, + "devDependencies": { + "in-publish": "^2.0.0", + "rimraf": "^2.4.3" + } +} diff --git a/src/app-host/app-host.js b/src/app-host/app-host.js new file mode 100644 index 00000000..1f285d13 --- /dev/null +++ b/src/app-host/app-host.js @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +var Messages = require('messages'); + +var cordova; +var oldExec; +var socket = io(); +var nextExecCacheIndex = 0; +var execCache = {}; +var pluginHandlers = {}; + +function setCordova(originalCordova) { + if (cordova) { + return; + } + + cordova = originalCordova; + + oldExec = cordova.require('cordova/exec'); + cordova.define.remove('cordova/exec'); + cordova.define('cordova/exec', function (require, exports, module) { + module.exports = exec; + }); + + // android platform has its own specific initialization + // so to emulate it, we need to fake init function + if (cordova.platformId === 'android') { + exec.init = function () { + cordova.require('cordova/channel').onNativeReady.fire(); + }; + } + + // windows phone platform fires 'deviceready' event from native component + // so to emulate it we fire it in the bootstrap function (similar to ios) + if (cordova.platformId === 'windowsphone') { + cordova.require('cordova/platform').bootstrap = function () { + cordova.require('cordova/channel').onNativeReady.fire(); + }; + } + + // default Windows bootstrap function tries to load WinJS which is not + // available and not required in simulation mode so we override bootstrap + if (cordova.platformId === 'windows') { + cordova.require('cordova/platform').bootstrap = function () { + cordova.require('cordova/modulemapper') + .clobbers('cordova/exec/proxy', 'cordova.commandProxy'); + + cordova.require('cordova/channel').onNativeReady.fire(); + }; + } +} + +function getCordova() { + return cordova; +} + +socket.on('exec-success', function (data) { + console.log('exec-success:'); + console.log(data); + var execCacheInfo = execCache[data.index]; + if (execCacheInfo.success) { + execCacheInfo.success(data.result); + } +}); + +socket.on('exec-failure', function (data) { + console.log('exec-failure:'); + console.log(data); + var execCacheInfo = execCache[data.index]; + if (execCacheInfo.fail) { + execCacheInfo.fail(data.error); + } +}); + +socket.emit('register-app-host'); + +function exec(success, fail, service, action, args) { + // If we have a local handler, call that. Otherwise pass it to the simulation host. + var handler = pluginHandlers[service] && pluginHandlers[service][action]; + if (handler) { + // Ensure local handlers are executed asynchronously. + setTimeout(function () { + handler(success, fail, service, action, args); + }, 0); + } else { + var execIndex = nextExecCacheIndex++; + execCache[execIndex] = {index: execIndex, success: success, fail: fail}; + socket.emit('exec', {index: execIndex, service: service, action: action, args: args}); + } +} + +// Setup for cordova.exec patching +Object.defineProperty(window, 'cordova', { + set: setCordova, + get: getCordova +}); + +function clobber(clobbers, scope) { + Object.keys(clobbers).forEach(function (key) { + if (clobbers[key] && typeof clobbers[key] === 'object') { + scope[key] = scope[key] || {}; + clobber(clobbers[key], scope[key]); + } else { + scope[key] = clobbers[key]; + } + }); +} + +// Details of each plugin that has app-host code is injected when this file is served. +var plugins = { + /** PLUGINS **/ +}; + +var pluginHandlersDefinitions = { + /** PLUGIN-HANDLERS **/ +}; + +var pluginClobberDefinitions = { + /** PLUGIN-CLOBBERS **/ +}; + +var pluginMessages = {}; +applyPlugins(plugins); +applyPlugins(pluginHandlersDefinitions, pluginHandlers); +applyPlugins(pluginClobberDefinitions, window); + +function applyPlugins(plugins, clobberScope) { + Object.keys(plugins).forEach(function (pluginId) { + var plugin = plugins[pluginId]; + if (plugin) { + if (typeof plugin === 'function') { + pluginMessages[pluginId] = pluginMessages[pluginId] || new Messages(pluginId, socket); + plugin = plugin(pluginMessages[pluginId], exec); + plugins[pluginId] = plugin; + } + if (clobberScope) { + clobber(plugin, clobberScope); + } + } + }); +} diff --git a/src/modules/argscheck.js b/src/modules/argscheck.js new file mode 100644 index 00000000..b17425d2 --- /dev/null +++ b/src/modules/argscheck.js @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Based in part on code from Apache Cordova (https://github.com/apache/cordova-js) + +var utils = require('utils'); + +var moduleExports = module.exports; + +var typeMap = { + 'A': 'Array', + 'D': 'Date', + 'N': 'Number', + 'S': 'String', + 'F': 'Function', + 'O': 'Object' +}; + +function extractParamName(callee, argIndex) { + return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex]; +} + +function checkArgs(spec, functionName, args, opt_callee) { + if (!moduleExports.enableChecks) { + return; + } + var errMsg = null; + var typeName; + for (var i = 0; i < spec.length; ++i) { + var c = spec.charAt(i), + cUpper = c.toUpperCase(), + arg = args[i]; + // Asterix means allow anything. + if (c == '*') { + continue; + } + typeName = utils.typeName(arg); + if ((arg === null || arg === undefined) && c == cUpper) { + continue; + } + if (typeName != typeMap[cUpper]) { + errMsg = 'Expected ' + typeMap[cUpper]; + break; + } + } + if (errMsg) { + errMsg += ', but got ' + typeName + '.'; + errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg; + // Don't log when running unit tests. + if (typeof jasmine == 'undefined') { + console.error(errMsg); + } + throw TypeError(errMsg); + } +} + +function getValue(value, defaultValue) { + return value === undefined ? defaultValue : value; +} + +moduleExports.checkArgs = checkArgs; +moduleExports.getValue = getValue; +moduleExports.enableChecks = true; + diff --git a/src/modules/db.js b/src/modules/db.js new file mode 100644 index 00000000..f2ba67ac --- /dev/null +++ b/src/modules/db.js @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Based in part on code from Apache Ripple, https://github.com/apache/incubator-ripple + +var Q = require('q'), + utils = require('utils'), + constants = require('sim-constants'), + event = require('event'), + DB_NAME = 'ripple', + cache, + self, + opendb; + +// TODO: This could use some refactoring.. + +function saveToStorage() { + localStorage[DB_NAME] = JSON.stringify(cache); +} + +function validateAndSetPrefix(prefix) { + if (prefix) { + utils.validateArgumentType(prefix, 'string'); + } + + return prefix || constants.COMMON.PREFIX; +} + +function createKey(key, prefix) { + return validateAndSetPrefix(prefix) + key; +} + +function createItem(key, value, prefix) { + return { + id: createKey(key, prefix), + key: key, + value: value, + prefix: validateAndSetPrefix(prefix) + }; +} + +function save(key, value, prefix, callback) { + var item = createItem(key, value, prefix); + cache[item.id] = item; + + if (!window.openDatabase) { + saveToStorage(); + if (callback) { callback(); } + } else { + opendb.transaction(function (tx) { + tx.executeSql('REPLACE INTO persistence (id, key, value, prefix) VALUES (?, ?, ?, ?)', [item.id, item.key, item.value, item.prefix], function () { + return callback && callback(); + }); + }); + } +} + +function retrieve(key, prefix) { + var item = cache[createKey(key, prefix)]; + return item ? item.value : undefined; +} + +function retrieveAll(prefix, callback) { + var result = {}; + + if (prefix) { + utils.forEach(cache, function (value) { + if (value.prefix === prefix) { + result[value.key] = value.value; + } + }); + } + + if (callback) { callback(result); } +} + +function remove(key, prefix, callback) { + var id = createKey(key, prefix); + + delete cache[id]; + + if (!window.openDatabase) { + saveToStorage(); + if (callback) { callback(); } + } else { + opendb.transaction(function (tx) { + tx.executeSql('DELETE FROM persistence WHERE key = ? AND prefix = ?', [key, validateAndSetPrefix(prefix)], function () { + return callback && callback(); + }); + }); + } +} + +function removeAll(callback) { + cache = {}; + + if (!window.openDatabase) { + delete localStorage[DB_NAME]; + saveToStorage(); + } else { + opendb.transaction(function (tx) { + tx.executeSql('DELETE FROM persistence', [], function () { + return callback && callback(); + }); + }); + } +} + +self = { + save: function (key, value, prefix, callback) { + save(key, value, prefix, callback); + event.trigger('StorageUpdatedEvent'); + }, + + saveObject: function (key, obj, prefix, callback) { + save(key, JSON.stringify(obj), prefix, callback); + event.trigger('StorageUpdatedEvent'); + }, + + retrieve: function (key, prefix) { + return retrieve(key, prefix); + }, + + retrieveObject: function (key, prefix) { + var retrievedValue = retrieve(key, prefix); + return retrievedValue ? JSON.parse(retrievedValue) : retrievedValue; + }, + + retrieveAll: function (prefix, callback) { + return retrieveAll(prefix, callback); + }, + + remove: function (key, prefix, callback) { + event.trigger('StorageUpdatedEvent'); + remove(key, prefix, callback); + }, + + removeAll: function (callback) { + removeAll(callback); + event.trigger('StorageUpdatedEvent'); + }, + + initialize: function (previous, baton) { + var d = Q.defer(); + + if (!window.openDatabase) { + var store = localStorage[DB_NAME]; + cache = store ? JSON.parse(store) : {}; + saveToStorage(); + d.resolve(); + } else { + cache = {}; + opendb = openDatabase('tinyHippos', '1.0', 'tiny Hippos persistence', 2 * 1024 * 1024); + opendb.transaction(function (tx) { + tx.executeSql('CREATE TABLE IF NOT EXISTS persistence (id unique, key, value, prefix)'); + + tx.executeSql('SELECT id, key, value, prefix FROM persistence', [], function (tx, results) { + var len = results.rows.length, i, item; + + for (i = 0; i < len; i++) { + item = results.rows.item(i); + cache[item.id] = item; + } + + d.resolve(); + }); + }); + } + + return d.promise; + } +}; + +module.exports = self; diff --git a/src/modules/event.js b/src/modules/event.js new file mode 100644 index 00000000..d8d99fb8 --- /dev/null +++ b/src/modules/event.js @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Based in part on code from Apache Ripple, https://github.com/apache/incubator-ripple + +var utils = require('utils'), + exception = require('exception'), + _listeners = {}; + +function _on(eventType, listener, scope, once) { + if (!eventType) { + throw "eventType must be truthy"; + } + _listeners[eventType] = _listeners[eventType] || []; + _listeners[eventType].push({ + func: listener, + scope: scope, + once: !!once + }); +} + +function _trigger(listener, args, sync) { + try { + if (sync) { + listener.func.apply(listener.scope, args); + } + else { + setTimeout(function () { + listener.func.apply(listener.scope, args); + }, 1); + } + } + catch (e) { + exception.handle(e); + } +} + +module.exports = { + on: function (eventType, listener, scope) { + _on(eventType, listener, scope, false); + }, + + once: function (eventType, listener, scope) { + _on(eventType, listener, scope, true); + }, + + trigger: function (eventType, args, sync) { + args = args || []; + sync = sync || false; + + var listeners = _listeners[eventType]; + + if (listeners) { + listeners.forEach(function (listener) { + _trigger(listener, args, sync); + }); + + _listeners[eventType] = listeners.filter(function (listener) { + return !listener.once; + }); + } + }, + + eventHasSubscriber: function (eventType) { + return !!_listeners[eventType]; + }, + + getEventSubscribers: function (eventType) { + return utils.copy(_listeners[eventType]) || []; + }, + + clear: function (eventType) { + if (eventType) { + delete _listeners[eventType]; + } + } +}; diff --git a/src/modules/exception.js b/src/modules/exception.js new file mode 100644 index 00000000..ce1936eb --- /dev/null +++ b/src/modules/exception.js @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Based in part on code from Apache Ripple, https://github.com/apache/incubator-ripple + +function _getStack(depth) { + var caller, + stack = '', + count = 0; + + try { + /*jshint noarg:false*/ // THIS SHOULD NOT be a common occurrence.. + caller = arguments.callee.caller.arguments.callee.caller; + + while (count <= depth && caller) { + stack += 'function: ' + caller.toString().match(/function\s?(.*)\{/)[1] + '\n'; + caller = caller.arguments.callee.caller; + count++; + } + } catch (e) { + stack = 'failed to determine stack trace (' + (e.name || e.type) + ' :: ' + e.message + ')'; + } + + return stack; +} + +module.exports = { + + types: { + Application: 'Application', + ArgumentLength: 'ArgumentLength', + ArgumentType: 'ArgumentType', + Argument: 'Argument', + NotificationType: 'NotificationType', + NotificationStateType: 'NotificationStateType', + DomObjectNotFound: 'DomObjectNotFound', + LayoutType: 'LayoutType', + DeviceNotFound: 'DeviceNotFound', + tinyHipposMaskedException: 'tinyHipposMaskedException', + Geo: 'Geo', + Accelerometer: 'Accelerometer', + MethodNotImplemented: 'MethodNotImplemented', + InvalidState: 'InvalidState', + ApplicationState: 'ApplicationState' + }, + + handle: function handle(exception, reThrow) { + reThrow = reThrow || false; + + var eMsg = exception.message || 'exception caught!', + msg = eMsg + '\n\n' + (exception.stack || '*no stack provided*') + '\n\n'; + + console.error(msg); + + if (reThrow) { + throw exception; + } + }, + + raise: function raise(exceptionType, message, customExceptionObject) { + var obj = customExceptionObject || { + type: '', + message: '', + + toString: function () { + var result = this.name + ': \'' + this.message + '\''; + + if (this.stack) { + result += '\n' + this.stack; + } + return result; + } + }; + + message = message || ''; + + obj.name = exceptionType; + obj.type = exceptionType; + // TODO: include the exception objects original message if exists + obj.message = message; + obj.stack = _getStack(5); + + throw obj; + } +}; diff --git a/src/modules/messages.js b/src/modules/messages.js new file mode 100644 index 00000000..c94aae8f --- /dev/null +++ b/src/modules/messages.js @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +var Q = require('q'); + +// Plugin communications layer. Two types of communication are supported: +// 1. Messages - when emitted, any local handlers are notified, and it is also sent across to web sockets connection +// where any remote handlers are notified. There can be any number of local and/or remote handlers. There is no +// opportunity to respond. +// 2. Methods - calls across the web socket connection where there can be a single handler that can return a single +// value or error value. + +function Messages(pluginId, socket) { + this.pluginId = pluginId; + this.socket = socket; + this.messages = {}; + this.methods = {}; + + var that = this; + socket.on('plugin-message', function (data) { + if (data.pluginId === pluginId) { + notify.call(that, data.message, data.data); + } + }); + socket.on('plugin-method', function (data, callback) { + if (data.pluginId === pluginId) { + var handler = that.methods && that.methods[data.method]; + if (handler) { + var args = data.args; + args.push(callback); + handler.apply(this, data.args); + } + } + }); +} + +function notify(message, data) { + // Notifies local listeners of a message + var handlers = this.messages && this.messages[message]; + if (handlers) { + handlers.forEach(function (handler) { + handler.call(this, message, data); + }); + } +} + +Messages.prototype = { + // Call and register for methods + + /** + * @desc Calls the specified method, with any number of parameters. Return a promise. + * @param method + */ + call: function (method) { + var d = Q.defer(); + this.socket.emit('plugin-method', { + pluginId: this.pluginId, + method: method, + args: Array.prototype.slice.call(arguments, 1) + }, function (err, result) { + if (err) { + d.reject(err); + } else { + d.resolve(result); + } + }); + return d.promise; + }, + + register: function(method, handler) { + // Can only ever have one handler for a method. Cancel by calling with handler null or undefined. + this.methods[method] = handler; + return this; + }, + + // Emit and handle messages + + emit: function (message, data) { + // Pass the message across the socket + this.socket.emit('plugin-message', { + pluginId: this.pluginId, + message: message, + data: data + }); + + // Notify any local listeners + notify.call(this, message, data); + }, + + on: function (message, handler) { + if (!this.messages[message]) { + this.messages[message] = [handler]; + } else { + this.messages[message].push(handler); + } + return this; + }, + + off: function (message, handler) { + var handlers = this.messages[message]; + if (!handlers) { + return this; + } + + var pos = handlers.indexOf(handler); + while (pos > -1) { + handlers.splice(pos, 1); + pos = handlers.indexOf(handler); + } + } +}; + +module.exports = Messages; diff --git a/src/modules/sim-constants.js b/src/modules/sim-constants.js new file mode 100644 index 00000000..8d5f2125 --- /dev/null +++ b/src/modules/sim-constants.js @@ -0,0 +1,214 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Based in part on code from Apache Ripple, https://github.com/apache/incubator-ripple + +module.exports = { + "API_URL": "https://rippleapi.herokuapp.com", + + "SERVICES": { + "GOOGLE_MAPS_URI": "http://maps.google.com/maps/api/staticmap?size=476x476&maptype=roadmap", + "GOOGLE_MAPS_API_KEY": "ABQIAAAA-CaPZHXR-0Tzhui_h6gpjhSE_2rGlnYiB7L-ZGVwgaut5s7OYRSlBAaHCzBuZf2_23_vrCOfPxXHjA" + }, + + "FS_SIZE": 1024 * 1024 * 10, + + "COMMON": { + "APPLICATION_STATE": "ui-application-state-", + "PREFIX": "tinyhippos-", + "MENU_BUTTON" : "menu-button", + "BACK_BUTTON" : "back-button", + "HTML_CONTAINER" : "document", + "INFO_SECTION": "information-sub-container", + "ORIENTATION_SELECT_PORTRAIT_ID" : "layout-portrait", + "ORIENTATION_SELECT_LANDSCAPE_ID" : "layout-landscape", + "PLATFORM_SELECT_ID": "platform-select", + "DEVICE_SELECT_ID": "device-select", + "STORAGE_TABLE_BODY_CLASS": "preferences-list-body", + "STORAGE_COUNT_CONTAINER_ID": "preferences-count", + "GEO_MAP_CONTAINER_ID": "geo-map", + "FILESYSTEM_UPDATE_BUTTON_ID_WITH_HASH": "#update-filesystem-button", + "APPLICATIONS_CONTAINER_ID": "widget-applications-content", + "STORAGE_CLEAR_BUTTON_ID": "preferences-clear-button", + "CHANGE_PLATFORM_BUTTON_ID": "change-platform", + "AJAX_LOADER_CONTAINER_CLASS": ".loader", + "IRRELEVANT_CLASS": "irrelevant", + "MULTIMEDIA_VOLUME_SLIDER_ID": "media-volume", + "MULTIMEDIA_VOLUME_FIELD_ID": "media-volume-value", + "MULTIMEDIA_AUDIO_STATE_FIELD_ID": "media-audio-state", + "MULTIMEDIA_AUDIO_PLAYING_FIELD_ID": "multimedia-isaudioplaying", + "MULTIMEDIA_AUDIO_PROGRESS_ID": "media-audio-progress", + "MULTIMEDIA_AUDIO_FILE_FIELD_ID": "media-audio-file", + "MULTIMEDIA_VIDEO_STATE_FIELD_ID": "media-video-state", + "MULTIMEDIA_VIDEO_PLAYING_FIELD_ID": "multimedia-isvideoplaying", + "MULTIMEDIA_VIDEO_PROGRESS_ID": "media-video-progress", + "MULTIMEDIA_VIDEO_FILE_FIELD_ID": "media-video-file", + "EXTENSION_URL_CONTAINER": "extension-url", + "SECURITY_LEVEL": "security-level" + }, + + "FILESYSTEM": { + "PERSISTENCE_KEY": "filesystem", + "INPUT_PREFIX_ID": "#panel-filesystem-" + }, + + "PLATFORM": { + "DEFAULT": { + "name": "cordova", + "version": "1.0.0" + } + }, + + "ENCAPSULATOR": { + "DEFAULT_HEIGHT": 684, + "DEFAULT_WIDTH": 480 + }, + + "GEO": { + "OPTIONS" : { + "LATITUDE" : "geo-latitude", + "LONGITUDE" : "geo-longitude", + "ALTITUDE" : "geo-altitude", + "CELL_ID" : "geo-cellid", + "ACCURACY" : "geo-accuracy", + "ALTITUDE_ACCURACY" : "geo-altitude-accuracy", + "HEADING" : "geo-heading", + "SPEED" : "geo-speed", + "TIME_STAMP" : "geo-timestamp", + "DELAY" : "geo-delay", + "DELAY_LABEL" : "geo-delay-label", + "HEADING_LABEL" : "geo-heading-label", + "HEADING_MAP_LABEL" : "geo-map-direction-label", + "IMAGE" : "geo-map-img", + "MAP_MARKER" : "geo-map-marker", + "MAP_CONTAINER" : "geo-map-container", + "TIMEOUT" : "geo-timeout", + "GPXFILE": "geo-gpxfile", + "GPXGO": "geo-gpx-go", + "GPXMULTIPLIER": "geo-gpxmultiplier-select", + "GPXREPLAYSTATUS": "geo-gpxreplaystatus" + }, + "MAP_ZOOM_MAX": 21, + "MAP_ZOOM_MIN": 0, + "MAP_ZOOM_LEVEL_CONTAINER": "geo-map-zoomlevel-value", + "MAP_ZOOM_KEY": "geo-map-zoom-key", + "GPXGO_LABELS": { + "GO": "Go", + "STOP": "Stop" + } + }, + + "PUSH": { + "OPTIONS" : { + "PAYLOAD" : "push-text" + } + }, + + "TELEPHONY": { + "CALL_LIST_KEY": "telephony-call-list-key" + }, + + "PIM": { + "ADDRESS_LIST_KEY": "pim-address-list-key", + "CALENDAR_LIST_KEY": "pim-calendar-list-key" + }, + + "CAMERA": { + "WINDOW_ANIMATION": "images/dance.gif", + "WARNING_TEXT": "The runtime simulated saving the camera file to {file}. If you need to access this file in your application, please copy a file to the saved location" + }, + + "AUDIOPLAYER" : { + "WARNING_TEXT": "The runtime simulated saving the audio file to {file}. If you need to access this file in your application, please copy a file to the saved location" + }, + + "API_APPLICATION": { + "NO_APPLICATIONS_MESSAGE": "No applications available for your platform" + }, + + "NOTIFICATIONS": { + "MESSAGE_CONTAINER_CLASS": "notification-message-div", + "MAIN_CONTAINER_CLASS": "panel-notification", + "CLOSE_BUTTON_CLASS": "panel-notification-closebtn", + "MESSAGE_TEXT_CONTAINER_CLASS": "panel-notification-text", + "CSS_PREFIX": "panel-notification-", + "STATE_TYPES": { + "OPEN": 1, + "CLOSE": 2 + } + }, + + "BATTERY_STATUS" : { + "BATTERY_STATUS_KEY": "battery-status-key", + "IS_PLUGGED_KEY" : "is-plugged-key", + "LEVEL_LABEL" : "battery-level-label", + "LEVEL_VALUE" : "battery-level", + "IS_PLUGGED_CHECKBOX" : "is-plugged" + }, + + "CSS_PREFIX": { + "IRRELEVANT" : "irrelevant" + }, + + "STORAGE": { + "PAIR_DELIMETER" : ",", + "KEY_VALUE_DELIMETER" : "|" + }, + + "REGEX": { + "GEO" : /^geo-/, + "URL": /^((https?|ftp|gopher|telnet|file|notes|ms-help):((\/\/)|(\\\\))+[\w\d:#@%\/;$()~_?\+-=\\\.&]*)$/, + //"Email": /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/ + "EMAIL": /^([^@\s]+)@((?:[\-a-z0-9]+\.)+[a-z]{2,})$/, + "WC3_DTF": /^((\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)|(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)|(\d{4})-(\d\d)-(\d\d)|(\d{4})-(\d\d)|(\d\d\d\d))$/, + "NON_RELATIVE_URI": /^https?:\/\/|^file:\/\// + }, + + "CONFIG": { + "SUCCESS_CSS": { + "true": "ui-text-pass", + "false": "ui-text-fail", + "missing": "ui-text-missing" + } + }, + + "SETTINGS": { + "TOOLTIPS_TOGGLE_DIV": "#settings-toggletooltips", + "TOOLTIPS_KEY": "tool-tips-key" + }, + + "UI": { + "JQUERY_UI_BUTTON_CLASSES": "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only", + "JQUERY_UI_INPUT_CLASSES": "ui-state-default ui-corner-all", + "PANEL_TABLE_CLASS": "panel-table", + "RIGHT_RANGE_LABEL_CLASS": "range-label", + "LEFT_RANGE_LABEL_CLASS": "range-label-left", + "TEXT_LABEL_CLASS": "ui-text-label", + "SCREEN_PPI": 96 + }, + + "MULTIMEDIA": { + "AUDIO_STATES": { + "OPENED": "opened", + "STOPPED": "stopped", + "PAUSED": "paused", + "PLAYING": "playing", + "COMPLETED": "completed" + } + }, + + "LANG": { + "ISO6392_LIST": ["abk", "ace", "ach", "ada", "ady", "aar", "afh", "afr", "afa", "ain", "aka", "akk", "alb/sqi", "gsw", "ale", "alg", "tut", "amh", "anp", "apa", "ara", "arg", "arp", "arw", "arm/hye", "rup", "art", "asm", "ast", "ath", "aus", "map", "ava", "ave", "awa", "aym", "aze", "ban", "bat", "bal", "bam", "bai", "bad", "bnt", "bas", "bak", "baq/eus", "btk", "bej", "bel", "bem", "ben", "ber", "bho", "bih", "bik", "byn", "bin", "bis", "zbl", "nob", "bos", "bra", "bre", "bug", "bul", "bua", "bur/mya", "cad", "spa", "cat", "cau", "ceb", "cel", "cai", "khm", "chg", "cmc", "cha", "che", "chr", "nya", "chy", "chb", "chi/zho", "chn", "chp", "cho", "zha", "chu", "chk", "chv", "nwc", "syc", "rar", "cop", "cor", "cos", "cre", "mus", "crp", "cpe", "cpf", "cpp", "crh", "hrv", "cus", "cze/ces", "dak", "dan", "dar", "del", "div", "zza", "din", "doi", "dgr", "dra", "dua", "dut/nld", "dum", "dyu", "dzo", "frs", "efi", "egy", "eka", "elx", "eng", "enm", "ang", "myv", "epo", "est", "ewe", "ewo", "fan", "fat", "fao", "fij", "fil", "fin", "fiu", "fon", "fre/fra", "frm", "fro", "fur", "ful", "gaa", "gla", "car", "glg", "lug", "gay", "gba", "gez", "geo/kat", "ger/deu", "nds", "gmh", "goh", "gem", "kik", "gil", "gon", "gor", "got", "grb", "grc", "gre/ell", "kal", "grn", "guj", "gwi", "hai", "hat", "hau", "haw", "heb", "her", "hil", "him", "hin", "hmo", "hit", "hmn", "hun", "hup", "iba", "ice/isl", "ido", "ibo", "ijo", "ilo", "arc", "smn", "inc", "ine", "ind", "inh", "ina", "ile", "iku", "ipk", "ira", "gle", "mga", "sga", "iro", "ita", "jpn", "jav", "kac", "jrb", "jpr", "kbd", "kab", "xal", "kam", "kan", "kau", "pam", "kaa", "krc", "krl", "kar", "kas", "csb", "kaw", "kaz", "kha", "khi", "kho", "kmb", "kin", "kir", "tlh", "kom", "kon", "kok", "kor", "kos", "kpe", "kro", "kua", "kum", "kur", "kru", "kut", "lad", "lah", "lam", "day", "lao", "lat", "lav", "ltz", "lez", "lim", "lin", "lit", "jbo", "dsb", "loz", "lub", "lua", "lui", "smj", "lun", "luo", "lus", "mac/mkd", "mad", "mag", "mai", "mak", "mlg", "may/msa", "mal", "mlt", "mnc", "mdr", "man", "mni", "mno", "glv", "mao/mri", "arn", "mar", "chm", "mah", "mwr", "mas", "myn", "men", "mic", "min", "mwl", "moh", "mdf", "rum/ron", "mkh", "lol", "mon", "mos", "mul", "mun", "nqo", "nah", "nau", "nav", "nde", "nbl", "ndo", "nap", "new", "nep", "nia", "nic", "ssa", "niu", "zxx", "nog", "non", "nai", "frr", "sme", "nso", "nor", "nno", "nub", "iii", "nym", "nyn", "nyo", "nzi", "oci", "pro", "oji", "ori", "orm", "osa", "oss", "oto", "pal", "pau", "pli", "pag", "pan", "pap", "paa", "pus", "per/fas", "peo", "phi", "phn", "pon", "pol", "por", "pra", "que", "raj", "rap", "qaa-qtz", "roa", "roh", "rom", "run", "rus", "sal", "sam", "smi", "smo", "sad", "sag", "san", "sat", "srd", "sas", "sco", "sel", "sem", "srp", "srr", "shn", "sna", "scn", "sid", "sgn", "bla", "snd", "sin", "sit", "sio", "sms", "den", "sla", "slo/slk", "slv", "sog", "som", "son", "snk", "wen", "sot", "sai", "alt", "sma", "srn", "suk", "sux", "sun", "sus", "swa", "ssw", "swe", "syr", "tgl", "tah", "tai", "tgk", "tmh", "tam", "tat", "tel", "ter", "tet", "tha", "tib/bod", "tig", "tir", "tem", "tiv", "tli", "tpi", "tkl", "tog", "ton", "tsi", "tso", "tsn", "tum", "tup", "tur", "ota", "tuk", "tvl", "tyv", "twi", "udm", "uga", "uig", "ukr", "umb", "mis", "und", "hsb", "urd", "uzb", "vai", "ven", "vie", "vol", "vot", "wak", "wln", "war", "was", "wel/cym", "fry", "wal", "wol", "xho", "sah", "yao", "yap", "yid", "yor", "ypk", "znd", "zap", "zen", "zul", "zun"] + }, + + "XHR": { + PROXY_SETTING: "settings-xhr-proxy-setting", + PROXY_SETTINGS_LIST: { + remote: "remote", + local: "local", + disabled: "disabled" + }, + DEFAULT_LOCAL_PORT: 4400, + DEFAULT_LOCAL_ROUTE: "/ripple", + LOCAL_PROXY_PORT_SETTING: "settings-xhr-proxy-local-port", + LOCAL_PROXY_ROUTE_SETTING: "settings-xhr-proxy-local-route" + } +}; diff --git a/src/modules/sim-host/dialog.js b/src/modules/sim-host/dialog.js new file mode 100644 index 00000000..a168c7a9 --- /dev/null +++ b/src/modules/sim-host/dialog.js @@ -0,0 +1,83 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +// This module manages the queuing of dialogs. The simulation host must register dialogs (by adding them to +// pluginDialogs) and handle the actual showing/hiding when requested (via hide() and show() methods attach to +// the registered dialog object). + +var pluginDialogs = {}; + +var currentDialogId = null; +var dialogQueue = []; + +module.exports.pluginDialogs = pluginDialogs; + +function showDialog(dialogId, cb) { + var dialog = pluginDialogs[dialogId]; + if (!dialog) { + throw 'No dialog defined with id ' + dialogId; + } + + // If a dialog is currently showing, queue this one to show later + if (currentDialogId) { + dialogQueue.push({id: dialogId, callback: cb}); + return; + } + + // Notify callback we're about to show + cb && cb('showing'); + + currentDialogId = dialogId; + + dialog.show(); + + // Notify callback we're shown + cb && cb('shown'); +} +module.exports.showDialog = showDialog; + +function hideDialog(dialogId) { + if (!dialogId) { + dialogId = currentDialogId; + if (!dialogId) { + throw 'Trying to hide dialog when none is showing.'; + } + } else { + if (dialogId !== currentDialogId) { + throw 'Trying to hide a dialog that isn\'t currently showing: ' + dialogId; + } + } + + var dialog = pluginDialogs[dialogId]; + if (!dialog) { + throw 'No dialog defined with id ' + dialogId; + } + + currentDialogId = null; + dialog.hide(); + + // After a timeout, see if there are more dialogs to show + window.setTimeout(function () { + if (currentDialogId) { + return; + } + + var dialogInfo = findNextDialog(); + if (dialogInfo) { + showDialog(dialogInfo.id, dialogInfo.callback); + } + }, 0); +} +module.exports.hideDialog = hideDialog; + +function findNextDialog() { + while (dialogQueue.length) { + var dialogInfo = dialogQueue.shift(); + var cb = dialogInfo.callback; + // If there's a callback, it must explicitly return 'false' (not a falsy value) in response to 'query-show' to + // prevent the dialog from showing. + if (!cb || cb('query-show') !== false) { + return dialogInfo; + } + } + return null; +} diff --git a/src/modules/utils.js b/src/modules/utils.js new file mode 100644 index 00000000..a26e07e3 --- /dev/null +++ b/src/modules/utils.js @@ -0,0 +1,171 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Based in part on code from Apache Ripple, https://github.com/apache/incubator-ripple + +var self, + exception = require('exception'); + +self = module.exports = { + validateArgumentType: function (arg, argType, customExceptionType, customExceptionMessage, customExceptionObject) { + var invalidArg = false, + msg; + + switch (argType) { + case 'array': + if (!(arg instanceof Array)) { + invalidArg = true; + } + break; + case 'date': + if (!(arg instanceof Date)) { + invalidArg = true; + } + break; + case 'integer': + if (typeof arg === 'number') { + if (arg !== Math.floor(arg)) { + invalidArg = true; + } + } + else { + invalidArg = true; + } + break; + default: + if (typeof arg !== argType) { + invalidArg = true; + } + break; + } + + if (invalidArg) { + msg = customExceptionMessage + ('\n\nInvalid Argument type. argument: ' + arg + ' ==> was expected to be of type: ' + argType); + exception.raise((customExceptionType || exception.types.ArgumentType), msg, customExceptionObject); + } + }, + + forEach: function (obj, action, scope) { + if (obj instanceof Array) { + return obj.forEach(action, scope); + } + else { + self.map(obj, action, scope); + } + }, + + map: function (obj, func, scope) { + var i, + returnVal = null, + result = []; + + //MozHack for NamedNodeMap + /* jshint ignore:start */ + if (window.MozNamedAttrMap) { + NamedNodeMap = window.MozNamedAttrMap; + } + /* jshint ignore:end */ + + if (obj instanceof Array) { + return obj.map(func, scope); + } + else if (obj instanceof NamedNodeMap) { + for (i = 0; i < obj.length; i++) { + returnVal = func.apply(scope, [obj[i], i]); + result.push(returnVal); + } + } + else { + for (i in obj) { + if (obj.hasOwnProperty(i)) { + returnVal = func.apply(scope, [obj[i], i]); + result.push(returnVal); + } + } + } + + return result; + }, + + bindAutoSaveEvent: function (selector, saveCallback) { + var oldSetTimeoutId; + + var node = document.querySelector(selector); + + if (!node) { + console.log('AUTO SAVE: REINSTATE ONCE WE HAVE ' + selector + ' ELEMENT'); + return; + } + + node.addEventListener('keyup', function (event) { + if (event.keyCode !== 9) { + clearTimeout(oldSetTimeoutId); + oldSetTimeoutId = window.setTimeout(function () { + saveCallback(); + }, 500); + } + }); + }, + + copy: function (obj) { + var i, + newObj = Array.isArray(obj) ? [] : {}; + + if (typeof obj === 'number' || + typeof obj === 'string' || + typeof obj === 'boolean' || + obj === null || + obj === undefined) { + return obj; + } + + if (obj instanceof Date) { + return new Date(obj); + } + + if (obj instanceof RegExp) { + return new RegExp(obj); + } + + for (i in obj) { + if (obj.hasOwnProperty(i)) { + if (obj[i] && typeof obj[i] === 'object') { + if (obj[i] instanceof Date) { + newObj[i] = obj[i]; + } + else { + newObj[i] = self.copy(obj[i]); + } + } + else { + newObj[i] = obj[i]; + } + } + } + + return newObj; + }, + + createUUID: function () { + return createUUIDPart(4) + '-' + + createUUIDPart(2) + '-' + + createUUIDPart(2) + '-' + + createUUIDPart(2) + '-' + + createUUIDPart(6); + }, + + typeName: function (val) { + return Object.prototype.toString.call(val).slice(8, -1); + } +}; + +function createUUIDPart(length) { + var uuidpart = ""; + for (var i = 0; i < length; i++) { + var uuidchar = parseInt((Math.random() * 256), 10).toString(16); + if (uuidchar.length == 1) { + uuidchar = "0" + uuidchar; + } + uuidpart += uuidchar; + } + return uuidpart; +} + diff --git a/src/platforms/android/sim-host-handlers.js b/src/platforms/android/sim-host-handlers.js new file mode 100644 index 00000000..1105a1af --- /dev/null +++ b/src/platforms/android/sim-host-handlers.js @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = { + 'CoreAndroid': { + 'show': function (success, fail, service, action, args) { + success(); + }, + 'messageChannel': function (success, fail, service, action, args) { + // This call is used to communicate the messageChannel callback to the native Java code. Since we don't need + // that, we just swallow this and do nothing. + } + } +}; diff --git a/src/platforms/windows/app-host-clobbers.js b/src/platforms/windows/app-host-clobbers.js new file mode 100644 index 00000000..b34b3e62 --- /dev/null +++ b/src/platforms/windows/app-host-clobbers.js @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = { + // Сlobbing WinJS.Application.addEventListener + // for proper cordova-plugin-test-framework initialization + // on Windows platform + WinJS: { + Application: { + addEventListener: function () {} + } + } +}; diff --git a/src/plugins/cordova-plugin-camera/app-host-clobbers.js b/src/plugins/cordova-plugin-camera/app-host-clobbers.js new file mode 100644 index 00000000..57b3b300 --- /dev/null +++ b/src/plugins/cordova-plugin-camera/app-host-clobbers.js @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = { + // This variable is required on Windows so that plugin works + Windows: { + Storage: { + ApplicationData: { + current: {} + }, + CreationCollisionOption: { + generateUniqueName: function () {} + }, + FileIO: {}, + Pickers: { + PickerLocationId: {} + } + }, + Media: { + Capture: { + MediaStreamType: {} + } + }, + UI: { + WebUI: { + WebUIApplication: {} + } + } + } +}; diff --git a/src/plugins/cordova-plugin-camera/app-host-handlers.js b/src/plugins/cordova-plugin-camera/app-host-handlers.js new file mode 100644 index 00000000..a8bb5794 --- /dev/null +++ b/src/plugins/cordova-plugin-camera/app-host-handlers.js @@ -0,0 +1,17 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = function (messages) { + return { + Camera: { + takePicture: function (success, fail, args) { + messages.call('takePicture', args).then(function (result) { + // 'result' should be {data: , type: }, from which we'll create a blob + var blob = new Blob([result.data], {type: result.type}); + success(URL.createObjectURL(blob)); + }, function (error) { + fail(error); + }); + } + } + }; +}; diff --git a/src/plugins/cordova-plugin-camera/sim-host-dialogs.html b/src/plugins/cordova-plugin-camera/sim-host-dialogs.html new file mode 100644 index 00000000..5b2e3027 --- /dev/null +++ b/src/plugins/cordova-plugin-camera/sim-host-dialogs.html @@ -0,0 +1,11 @@ + + + +
+ + Choose File + + Cancel + + +
diff --git a/src/plugins/cordova-plugin-camera/sim-host-panels.html b/src/plugins/cordova-plugin-camera/sim-host-panels.html new file mode 100644 index 00000000..457cd9ce --- /dev/null +++ b/src/plugins/cordova-plugin-camera/sim-host-panels.html @@ -0,0 +1,16 @@ + + + + + Use host system camera + Prompt me for a file + Use built-in sample file + + Use this file: + Choose File + + + + + + diff --git a/src/plugins/cordova-plugin-camera/sim-host.js b/src/plugins/cordova-plugin-camera/sim-host.js new file mode 100644 index 00000000..4c4ac14c --- /dev/null +++ b/src/plugins/cordova-plugin-camera/sim-host.js @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +var dialog = require('dialog'); + +module.exports = function (messages) { + var filenameInput, dialogFilenameInput, dialogImg; + + messages.register('takePicture', function (args, callback) { + if (document.getElementById('camera-host').checked) { + window.alert('Not supported'); + } else if (document.getElementById('camera-prompt').checked) { + dialog.showDialog('camera-choose-image', function (msg) { + if (msg === 'showing') { + // Not we use .onclick etc here rather than addEventListener() to ensure we replace any existing + // handler with one that uses the appropriate value of 'callback' from the current closure. + document.getElementById('camera-dialog-use-image').onclick = function () { + dialog.hideDialog('camera-choose-image'); + createArrayBuffer(dialogFilenameInput, callback); + }; + document.getElementById('camera-dialog-cancel').onclick = function () { + dialog.hideDialog('camera-choose-image'); + callback(null, null); + }; + } + }); + } else if (document.getElementById('camera-sample').checked) { + window.alert('Not supported'); + } else if (document.getElementById('camera-file').checked) { + createArrayBuffer(filenameInput, callback); + } + }); + + function createArrayBuffer(input, callback) { + var blob = input.files[0]; + var reader = new FileReader(); + reader.onloadend = function () { + callback(reader.error, {data: reader.result, type: blob.type}); + }; + reader.readAsArrayBuffer(blob); + } + + return { + initialize: function () { + filenameInput = document.getElementById('camera-filename'); + dialogFilenameInput = document.getElementById('camera-dialog-filename'); + dialogImg = document.getElementById('camera-dialog-image'); + var panelImg = document.getElementById('camera-img'); + + // Setup handlers for choosing an image in the panel + document.getElementById('camera-choose-filename').addEventListener('click', function () { + filenameInput.input.click(); + }); + + filenameInput.addEventListener('change', function () { + panelImg.src = URL.createObjectURL(filenameInput.files[0]); + panelImg.style.display = ''; + }); + + // Setup handlers for choosing an image in the dialog + document.getElementById('camera-dialog-choose-filename').addEventListener('click', function () { + dialogFilenameInput.input.click(); + }); + + dialogFilenameInput.addEventListener('change', function () { + dialogImg.src = URL.createObjectURL(dialogFilenameInput.files[0]); + dialogImg.style.display = ''; + document.getElementById('camera-dialog-use-image').style.display = ''; + }); + } + }; +}; diff --git a/src/plugins/cordova-plugin-console/sim-host-handlers.js b/src/plugins/cordova-plugin-console/sim-host-handlers.js new file mode 100644 index 00000000..e57f2ada --- /dev/null +++ b/src/plugins/cordova-plugin-console/sim-host-handlers.js @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = function (messages) { + function logLevelHandler(successCallback, errorCallback, args) { + var level = args[0]; + var message = args[1]; + switch (level) { + case 'LOG': window.console.log(message); break; + case 'ERROR': window.console.error('ERROR: ' + message); break; + case 'WARN': window.console.warn('WARN: ' + message); break; + case 'INFO': window.console.info('INFO: ' + message); break; + case 'DEBUG': window.console.debug('DEBUG: ' + message); break; + } + } + + return { + 'Console': { + 'logLevel': logLevelHandler, + } + }; +}; diff --git a/src/plugins/cordova-plugin-contacts/app-host-clobbers.js b/src/plugins/cordova-plugin-contacts/app-host-clobbers.js new file mode 100644 index 00000000..a8b6fbd9 --- /dev/null +++ b/src/plugins/cordova-plugin-contacts/app-host-clobbers.js @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = { + // This variable is required on Windows platform so that plugin works + Windows: { + ApplicationModel: { + Contacts: {} + } + }, + WinJS: { + Utilities: { + // While simulating Windows platform, we don't currently provide + // a way to specify Table/PC vs Phone simulation so we always + // retun false here; this may be changed in the future. + isPhone: false + } + } +}; diff --git a/src/plugins/cordova-plugin-contacts/app-host.js b/src/plugins/cordova-plugin-contacts/app-host.js new file mode 100644 index 00000000..1d6adbca --- /dev/null +++ b/src/plugins/cordova-plugin-contacts/app-host.js @@ -0,0 +1,77 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = function (messages) { + messages.register('pickContact', function (event, callback) { + var contacts = event; + + if (!contacts || contacts.length === 0) { + callback('No contacts found'); + return; + } + + var dlgWrap = document.createElement('div'); + dlgWrap.style.position = 'absolute'; + dlgWrap.style.width = '100%'; + dlgWrap.style.height = '100%'; + dlgWrap.style.backgroundColor = 'rgba(0,0,0,0.25)'; + dlgWrap.style.zIndex = '100000'; + dlgWrap.style.top = '0'; + dlgWrap.style.left = '0'; + dlgWrap.style.margin = '0'; + dlgWrap.style.padding = '0'; + + var dlg = document.createElement('div'); + dlg.style.height = 'auto'; + dlg.style.overflow = 'auto'; + dlg.style.backgroundColor = 'white'; + dlg.style.position = 'relative'; + dlg.style.lineHeight = '2'; + + dlg.style.top = '50%'; // center vertically + dlg.style.transform = 'translateY(-50%)'; + dlg.style.margin = '0px 30%'; + dlg.style.padding = '10px'; + dlg.style.boxShadow = '2px 2px 5px 1px rgba(0, 0, 0, 0.2)'; + dlg.style.borderRadius = '2px'; + + var titleStyle = 'border-top-left-radius: 2px; border-top-right-radius: 2px; position: relative; background-color: #03a9f4; color: #fff; font-size: 18px; padding: 7px 10px; height: 30px; text-transform: none; font-family: \'Helvetica Neue\', \'Roboto\', \'Segoe UI\', \'sans-serif\'; line-height: 24px; margin: -10px;'; + + // dialog layout template + var dlgHtml = '
'; + + dlg.innerHTML = dlgHtml; + + dlg.querySelector('#lbl-title').appendChild(document.createTextNode('Please pick a contact')); + + var ul = document.createElement('ul'); + ul.style.maxHeight = '500px'; + ul.style.overflow = 'auto'; + ul.style.listStyle = 'none'; + ul.style.padding = '0'; + contacts.forEach(function (contact) { + var li = document.createElement('li'); + var a = document.createElement('a'); + li.appendChild(a); + a.href = '#'; + a.style.color = '#3c8b9e'; + a.style.textTransform = 'none'; + a.style.fontSize = '14px'; + a.style.fontWeight = 'bold'; + a.style.margin = '20px 0 0 0'; + a.style.fontFamily = '\'Helvetica Neue\', \'Roboto\', \'Segoe UI\', \'sans-serif\''; + var contactInfo = contact.id; + if (contact.displayName !== null && contact.displayName !== '') { + contactInfo += ' (' + contact.displayName + ')'; + } + a.innerHTML = contactInfo; + a.addEventListener('click', function () { + dlgWrap.parentNode.removeChild(dlgWrap); + callback(false, contact); + }, false); + ul.appendChild(li); + }); + dlg.appendChild(ul); + dlgWrap.appendChild(dlg); + document.body.appendChild(dlgWrap); + }); +}; diff --git a/src/plugins/cordova-plugin-contacts/default-contacts.js b/src/plugins/cordova-plugin-contacts/default-contacts.js new file mode 100644 index 00000000..974aa347 --- /dev/null +++ b/src/plugins/cordova-plugin-contacts/default-contacts.js @@ -0,0 +1,91 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = [ + { + id: '53a547be-dea7-697e-0565-0c6cdfe48f62', + rawId:null, + displayName:'Dooney Evans', + name: { + formatted:'Dooney Evans', + familyName:'Evans', + givenName:'Dooney', + middleName:'' + }, + nickname:null, + phoneNumbers:[ + { + id:null, + type:'home', + value:'111-111-1111', + pref:true + } + ], + emails:null, + addresses:null, + ims:null, + organizations:null, + birthday:null, + note:null, + photos:null, + categories:null, + urls:null + }, + { + id: '64a5sdbe-dea7-6d7e-0565-0c6cddfghj62', + rawId:null, + displayName:'Jools Theobald', + name: { + formatted:'Jools Theobald', + familyName:'Theobald', + givenName:'Jools', + middleName:'' + }, + nickname:null, + phoneNumbers:[ + { + id:null, + type:'work', + value:'222-222-2222', + pref:true + } + ], + emails:null, + addresses:null, + ims:null, + organizations:null, + birthday:null, + note:null, + photos:null, + categories:null, + urls:null + }, + { + id: '876547be-ddfd-697e-0565-0c6kjjkl8f52', + rawId:null, + displayName:'Shelley Dusty', + name: { + formatted:'Shelley Dusty', + familyName:'Dusty', + givenName:'Shelley', + middleName:'' + }, + nickname:null, + phoneNumbers:[ + { + id:null, + type:'work', + value:'333-333-3333', + pref:true + } + ], + emails:null, + addresses:null, + ims:null, + organizations:null, + birthday:null, + note:null, + photos:null, + categories:null, + urls:null + } +]; diff --git a/src/plugins/cordova-plugin-contacts/sim-host-handlers.js b/src/plugins/cordova-plugin-contacts/sim-host-handlers.js new file mode 100644 index 00000000..bc9be945 --- /dev/null +++ b/src/plugins/cordova-plugin-contacts/sim-host-handlers.js @@ -0,0 +1,196 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +var db = require('db'); +var dbContactsObjectName = 'contacts'; +var defaultContacts = require('./default-contacts'); + +module.exports = function (messages) { + // load default contacts if no contacts were saved + var contacts = db.retrieveObject(dbContactsObjectName) || []; + if (contacts.length === 0) { + db.saveObject(dbContactsObjectName, defaultContacts); + } + + function save(success, fail, args) { + var contact = args[0]; + if (!contact.id) { + contact.id = generateGuid(); + } + var contacts = db.retrieveObject(dbContactsObjectName) || []; + var updateOperation = false; + for (var i = 0; i < contacts.length; i++) { + if (contacts[i].id === contact.id) { + contacts[i] = contact; + updateOperation = true; + } + } + if (!updateOperation) { + contacts.push(contact); + } else { + // Some contact properties uses arrays of specific objects + // in this case we should look at 'value' fields of these objects + // and remove these objects if 'value' is empty + for (var propIndex in contact) { + var property = contact[propIndex]; + // Check if property is Array + if (property !== null && Object.prototype.toString.call(property) === '[object Array]') { + for (var itemIndex in property) { + var item = property[itemIndex]; + if (item && typeof item.value !== 'undefined' && item.value === '') { + var emptyIndex = contact[propIndex].indexOf(item); + contact[propIndex].splice(emptyIndex, 1); + } + } + } + } + } + db.saveObject(dbContactsObjectName, contacts); + success(contact); + } + + function remove(success, fail, args) { + var id = args[0]; + var contacts = db.retrieveObject(dbContactsObjectName) || []; + var indexToDelete = null; + for (var i = 0; i < contacts.length; i++) { + if (contacts[i].id === id) { + indexToDelete = i; + break; + } + } + + if (indexToDelete !== null) { + contacts.splice(indexToDelete, 1); + db.saveObject(dbContactsObjectName, contacts); + success(); + } else { + // 0 refers to ContactError.UNKNOWN_ERROR + fail(0); + } + } + + function search(success, fail, args) { + var fields = args[0]; + var options = args[1]; + + var contacts = db.retrieveObject(dbContactsObjectName) || []; + + var queryResult = contacts.filter(function(contact) { + return isContactMatchesFilter(contact, options, fields); + }); + + if (!options.multiple && queryResult.length > 1) { + // select only first contact found + queryResult = [queryResult[0]]; + } + + queryResult = queryResult.map(function (contact) { + return extractDesiredFields(contact, options.desiredFields); + }); + + success(queryResult); + } + + function pickContact(success, fail, args) { + var contacts = db.retrieveObject(dbContactsObjectName) || []; + messages.call('pickContact', contacts).then(function (result) { + success(result); + }, function (err) { + fail(err); + }); + } + + function isContactMatchesFilter(contact, options, fields) { + // test special case (hasPhoneNumber option) + if (options.hasPhoneNumber && (!contact.phoneNumbers || contact.phoneNumbers.length === 0)) { + return false; + } + + // If filter is not set we assume contact matches it (used to return all contacts) + if (!options.filter || options.filter === '') { + return true; + } + + var contactField; + // Searching by all fields + if (fields.indexOf('*') !== -1) { + for (var index in contact) { + contactField = contact[index]; + if (isContactFieldMatchesFilter(contactField, options.filter)) { + return true; + } + } + } else { + // Searching only by fields specified in args + for (var fieldIndex in fields) { + var contactFieldName = fields[fieldIndex]; + contactField = contact[contactFieldName]; + if (isContactFieldMatchesFilter(contactField, options.filter)) { + return true; + } + } + } + return false; + } + + function isContactFieldMatchesFilter(field, filter) { + // If contact property contains several fields, + // we need to search through all of them + if (typeof field === 'object') { + for(var fieldIndex in field) { + if (isContactFieldMatchesFilter(field[fieldIndex], filter)) { + return true; + } + } + } else { // test standard type property + // special partial case insensitive comparison for strings + if (typeof field === 'string') { + return field && field.toLowerCase().indexOf(filter.toLowerCase()) >= 0; + } + // for non-strings + return field === filter; + } + return false; + } + + // if desired fields specified, we must return only these fields specified + function extractDesiredFields(contact, desiredFields) { + if (desiredFields && desiredFields.length > 0) { + var newContact = {}; + desiredFields.forEach(function (desired) { + newContact[desired] = contact[desired]; + }); + return newContact; + } else { + return contact; + } + } + + function notifyNotSupported(success, fail, args) { + fail('This method is not supported yet'); + } + + function generateGuid() { + function s4() { + return Math.floor((1 + Math.random()) * 0x10000) + .toString(16) + .substring(1); + } + return s4() + s4() + '-' + s4() + '-' + s4() + '-' + + s4() + '-' + s4() + s4() + s4(); + } + + return { + 'Contacts': { + // common exec's + 'pickContact': pickContact, + 'search': search, + 'save': save, + 'remove': remove, + // iOS specific exec's + 'chooseContact': notifyNotSupported, + 'displayContact': notifyNotSupported, + 'newContact': notifyNotSupported + } + }; +}; diff --git a/src/plugins/cordova-plugin-device-motion/3d.js b/src/plugins/cordova-plugin-device-motion/3d.js new file mode 100644 index 00000000..fe1dc884 --- /dev/null +++ b/src/plugins/cordova-plugin-device-motion/3d.js @@ -0,0 +1,243 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// Wii Opera SDK - 3D Math Class v2.7.22 2008-12-14 // +// (c) 2007-2008 Daniel Gump. All Rights Reserved. // +// http://wiioperasdk.com, http://hullbreachonline.com // +// hullbreach@hullbreachonline.com // +// // +// Wii is a trademark of Nintendo Co., Ltd. // +// Opera is a trademark of Opera, ASA. // +// This software package is not associated with either company // +// but was created to support users of both. Its alternative name // +// when supporting other products is the HULLBREACH SDK. // +// // +// Redistribution and use in source and binary forms, with or without // +// modification, are permitted provided that the following conditions // +// are met: // +// * Redistributions of source code must retain the above copyright // +// notice, this list of conditions and the following disclaimer. // +// * 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. // +// * Neither the names HULLBREACH ONLINE nor WII OPERA SDK nor the names // +// of its contributors may be used to endorse or promote products // +// derived from this software without specific prior written // +// permission. // +// * If the explicit purpose of the software is not to support the // +// Nintendo Wii or the Opera Web browser, then the names of such must // +// not be used in any derived product. The name shall be the // +// HULLBREACH SDK with a reference link to http://hullbreachonline. // +// // +// THIS SOFTWARE IS PROVIDED BY Daniel Gump ''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 Daniel Gump 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. // +////////////////////////////////////////////////////////////////////////////// + +function ThreeD(){ + POLYMESH = new Array(); + + CENTERX = 400; CENTERY = 240; + LIGHTX = -1000; LIGHTY = -1000; LIGHTZ = -1000; + ORIGINX = 0; ORIGINY = 0; ORIGINZ = 0; + ANGLEX = 0; ANGLEY = 0; ANGLEZ = 0; +} + +ThreeD.prototype.setPoints = function(Points){ + POLYMESH = []; + for(var value=Points.length;--value>=0;) POLYMESH[value] = Points[value].slice(); +} +ThreeD.prototype.loadMesh = function(array){ + if(POLYMESH = array.split(";")) for(i=POLYMESH.length;--i>=0;) POLYMESH[i] = POLYMESH[i].split(","); +} +ThreeD.prototype.getPoints = function(){ return POLYMESH; } + +ThreeD.prototype.setCenter = function(x,y){ CENTERX = x|0; CENTERY = y|0; } +ThreeD.prototype.setLight = function(x,y,z){ LIGHTX = x|0; LIGHTY = y|0; LIGHTZ = z|0; } + +ThreeD.prototype.explode = function(z){ + var x1, y1, z1, x2, y2, z2; + var normali, normalj, normalk, magNormal; + + for(var value=POLYMESH.length;--value>=0;){ + x1 = POLYMESH[value][3]-POLYMESH[value][0]; y1 = POLYMESH[value][4]-POLYMESH[value][1]; z1 = POLYMESH[value][5]-POLYMESH[value][2]; + x2 = POLYMESH[value][6]-POLYMESH[value][0]; y2 = POLYMESH[value][7]-POLYMESH[value][1]; z2 = POLYMESH[value][8]-POLYMESH[value][2]; + + normali = y2*z1-y1*z2; normalj = x1*z2-x2*z1; normalk = x2*y1-x1*y2; + magNormal = z/Math.sqrt(normali*normali+normalj*normalj+normalk*normalk); + + var movex = -normali*magNormal|0; + var movey = -normalj*magNormal|0; + var movez = -normalk*magNormal|0; + + POLYMESH[value][0] += movex; POLYMESH[value][1] += movey; POLYMESH[value][2] += movez; + POLYMESH[value][3] += movex; POLYMESH[value][4] += movey; POLYMESH[value][5] += movez; + POLYMESH[value][6] += movex; POLYMESH[value][7] += movey; POLYMESH[value][8] += movez; + } +} +ThreeD.prototype.normalMap = function(normalMap){ + var x1, y1, z1, x2, y2, z2; + var normali, normalj, normalk, magNormal; + + for(var value=POLYMESH.length;--value>=0;){ + x1 = POLYMESH[value][3]-POLYMESH[value][0]; y1 = POLYMESH[value][4]-POLYMESH[value][1]; z1 = POLYMESH[value][5]-POLYMESH[value][2]; + x2 = POLYMESH[value][6]-POLYMESH[value][0]; y2 = POLYMESH[value][7]-POLYMESH[value][1]; z2 = POLYMESH[value][8]-POLYMESH[value][2]; + + normali = y2*z1-y1*z2; normalj = x1*z2-x2*z1; normalk = x2*y1-x1*y2; + normal = 1/Math.sqrt(normali*normali+normalj*normalj+normalk*normalk); + + for(index2=0; index2<4; index2++){ + for(index=0; index<=index2; index++){ + magNormal = normalMap[index][index2]*normal|0; + + var movex = -normali*magNormal; + var movey = -normalj*magNormal; + var movez = -normalk*magNormal; + + POLYMESH[POLYMESH.length] = new Array(POLYMESH[value][0]+movex,POLYMESH[value][1]+movey,POLYMESH[value][2]+movez, + POLYMESH[value][3]+movex,POLYMESH[value][4]+movey,POLYMESH[value][7]+movez, + POLYMESH[value][6]+movex,POLYMESH[value][7]+movey,POLYMESH[value][8]+movez, + POLYMESH[value][9],POLYMESH[value][10],POLYMESH[value][11], + POLYMESH[value][12],POLYMESH[value][13], true, index, index2); + } + } + } +} +ThreeD.prototype.move = function(x,y,z){ + for(var value=POLYMESH.length;--value>=0;) + for(var point=-1;++point<3;){ + POLYMESH[value][point*3+2] += z; + POLYMESH[value][point*3+1] += y; + POLYMESH[value][point*3] += x; + } +} +ThreeD.prototype.rotate = function(anglex,angley,anglez){ + var cosx = Math.cos(anglex*0.01745329); var sinx = Math.sin(anglex*0.01745329); + var cosy = Math.cos(angley*0.01745329); var siny = Math.sin(angley*0.01745329); + var cosz = Math.cos(anglez*0.01745329); var sinz = Math.sin(anglez*0.01745329); + + for(var value=POLYMESH.length;--value>=0;) + for(var point=-1;++point<3;){ + var tempz = sinx*POLYMESH[value][point*3+1]+cosx*POLYMESH[value][point*3+2]; + var tempy = cosx*POLYMESH[value][point*3+1]-sinx*POLYMESH[value][point*3+2]; + var tempx = cosy*POLYMESH[value][point*3]+siny*tempz; + POLYMESH[value][point*3+2] = cosy*tempz-siny*POLYMESH[value][point*3]; + POLYMESH[value][point*3+1] = sinz*tempx+cosz*tempy; + POLYMESH[value][point*3] = cosz*tempx-sinz*tempy; + } +} +ThreeD.prototype.scale = function(scalex,scaley,scalez){ + for(var value=POLYMESH.length;--value>=0;) + for(var point=-1;++point<3;){ + POLYMESH[value][point*3+2] *= scalex; + POLYMESH[value][point*3+1] *= scaley; + POLYMESH[value][point*3] *= scalez; + } +} + +ThreeD.prototype.backface = function(){ + for(var value=POLYMESH.length, newvalue=0, TempPOLYMESH = [];--value>=0;) + if((POLYMESH[value][3]-POLYMESH[value][0])*(POLYMESH[value][7]-POLYMESH[value][1])-(POLYMESH[value][6]-POLYMESH[value][0])*(POLYMESH[value][4]-POLYMESH[value][1])>0){ + TempPOLYMESH[newvalue++] = POLYMESH[value].slice(); + } + POLYMESH = TempPOLYMESH; +} +ThreeD.prototype.zSort = function(){ POLYMESH.sort(function(b,a){return b[2]+b[5]+b[8]-a[2]-a[5]-a[8]}); } + +ThreeD.prototype.fade = function(bright){ + for(var value=POLYMESH.length;--value>=0;) POLYMESH[value][13] += bright; +} +ThreeD.prototype.shade = function(){ + var x1, y1, z1, x2, y2, z2; + var normali, normalj, normalk, magNormal; + var lighti, lightj, lightk, magLight; + + for(var value=POLYMESH.length;--value>=0;){ + x1 = POLYMESH[value][3]-POLYMESH[value][0]; y1 = POLYMESH[value][4]-POLYMESH[value][1]; z1 = POLYMESH[value][5]-POLYMESH[value][2]; + x2 = POLYMESH[value][6]-POLYMESH[value][0]; y2 = POLYMESH[value][7]-POLYMESH[value][1]; z2 = POLYMESH[value][8]-POLYMESH[value][2]; + + normali = y1*z2-y2*z1; normalj = x2*z1-x1*z2; normalk = x1*y2-x2*y1; + + lighti = LIGHTX-(POLYMESH[value][0]+POLYMESH[value][3]+POLYMESH[value][6])*0.33333333333333333; + lightj = LIGHTY-(POLYMESH[value][1]+POLYMESH[value][4]+POLYMESH[value][7])*0.33333333333333333; + lightk = LIGHTZ-(POLYMESH[value][2]+POLYMESH[value][5]+POLYMESH[value][8])*0.33333333333333333; + + POLYMESH[value][13] = 2*(normali*lighti + normalj*lightj + normalk*lightk)/Math.sqrt((normali*normali+normalj*normalj+normalk*normalk)*(lighti*lighti+lightj*lightj+lightk*lightk))-1; + } +} +ThreeD.prototype.reColor = function(r,g,b){ + r=r>255?255:(r<0?0:r|0); + g=g>255?255:(g<0?0:g|0); + b=b>255?255:(b<0?0:b|0); + for(var value=POLYMESH.length;--value>=0;){ + POLYMESH[value][9]=r; + POLYMESH[value][10]=g; + POLYMESH[value][11]=b; + } +} +ThreeD.prototype.shadow = function(){ + rayorigins = []; + raynormals = []; + edge1 = []; + edge2 = []; + + for(var value=0, normali, normalj, normalk, magNormal;value=0;){ + for(var value2=POLYMESH.length;--value2>=0;){ + if(value2!=value){ + var pvecti = raynormals[value][1]*edge2[value2][2]-edge2[value2][1]*raynormals[value][2]; + var pvectj = edge2[value2][0]*raynormals[value][2]-raynormals[value][0]*edge2[value2][2]; + var pvectk = raynormals[value][0]*edge2[value2][1]-edge2[value2][0]*raynormals[value][1]; + + if((det = edge1[value2][0]*pvecti+edge1[value2][1]*pvectj+edge1[value2][2]*pvectk)<0){ + det=1/det; + + var tvecti = rayorigins[value][0]-POLYMESH[value2][0]; + var tvectj = rayorigins[value][1]-POLYMESH[value2][1]; + var tvectk = rayorigins[value][2]-POLYMESH[value2][2]; + + if((u = (pvecti*tvecti+pvectj*tvectj+pvectk*tvectk) * det)>=0 && u<=1){ + if((v = (raynormals[value][0]*(tvectj*edge1[value2][2]-edge1[value2][1]*tvectk)+raynormals[value][1]*(edge1[value2][0]*tvectk-tvecti*edge1[value2][2])+raynormals[value][2]*(tvecti*edge1[value2][1]-edge1[value2][0]*tvectj)) * det)>=0 && u+v<=1){ + POLYMESH[value][13] -=.5; + break; + } + } + } + + } + } + } +} + +ThreeD.prototype.getTranslation = function(){ + for(var value=POLYMESH.length,newvalue=0,TransPOLYMESH = [];--value>=0;){ + var POLYMESH2=5000/(5000-POLYMESH[value][2]), POLYMESH5=5000/(5000-POLYMESH[value][5]), POLYMESH8=5000/(5000-POLYMESH[value][8]); + TransPOLYMESH[newvalue++] = new Array((CENTERX+POLYMESH[value][0]*POLYMESH2),(CENTERY+POLYMESH[value][1]*POLYMESH2), + (CENTERX+POLYMESH[value][3]*POLYMESH5),(CENTERY+POLYMESH[value][4]*POLYMESH5), + (CENTERX+POLYMESH[value][6]*POLYMESH8),(CENTERY+POLYMESH[value][7]*POLYMESH8), + POLYMESH[value][9]|0,POLYMESH[value][10]|0,POLYMESH[value][11]|0,POLYMESH[value][12]|0,POLYMESH[value][13]); + } + return TransPOLYMESH; +} + +ThreeDee = new ThreeD(); \ No newline at end of file diff --git a/src/plugins/cordova-plugin-device-motion/app-host-clobbers.js b/src/plugins/cordova-plugin-device-motion/app-host-clobbers.js new file mode 100644 index 00000000..7b0a10b4 --- /dev/null +++ b/src/plugins/cordova-plugin-device-motion/app-host-clobbers.js @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = { + // This is required for device-motion tests for windows platform. + Windows: { + Devices: { + Sensors: { + Accelerometer: { + getDefault: function () { return true; } + } + } + } + } +}; diff --git a/src/plugins/cordova-plugin-device-motion/draw.js b/src/plugins/cordova-plugin-device-motion/draw.js new file mode 100644 index 00000000..3e633087 --- /dev/null +++ b/src/plugins/cordova-plugin-device-motion/draw.js @@ -0,0 +1,235 @@ +////////////////////////////////////////////////////////////////////////////// +// // +// Wii Opera SDK - Drawing Class v2.6.16 2008-12-14 // +// (c) 2007-2008 Daniel Gump. All Rights Reserved. // +// http://wiioperasdk.com, http://hullbreachonline.com // +// hullbreach@hullbreachonline.com // +// // +// Wii is a trademark of Nintendo Co., Ltd. // +// Opera is a trademark of Opera, ASA. // +// This software package is not associated with either company // +// but was created to support users of both. Its alternative name // +// when supporting other products is the HULLBREACH SDK. // +// // +// Redistribution and use in source and binary forms, with or without // +// modification, are permitted provided that the following conditions // +// are met: // +// * Redistributions of source code must retain the above copyright // +// notice, this list of conditions and the following disclaimer. // +// * 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. // +// * Neither the names HULLBREACH ONLINE nor WII OPERA SDK nor the names // +// of its contributors may be used to endorse or promote products // +// derived from this software without specific prior written // +// permission. // +// * If the explicit purpose of the software is not to support the // +// Nintendo Wii or the Opera Web browser, then the names of such must // +// not be used in any derived product. The name shall be the // +// HULLBREACH SDK with a reference link to http://hullbreachonline. // +// // +// THIS SOFTWARE IS PROVIDED BY Daniel Gump ''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 Daniel Gump 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. // +////////////////////////////////////////////////////////////////////////////// + +function Drawing(){ + this.WIREFRAME = 1; this.FILL = 2; + ZOOM = 1; + CANVAS = null; + TEXTURES = null; +} +Drawing.prototype.initialize = function(canvas){ + CANVAS = canvas.getContext("2d"); + CANVAS.lineJoin = "round"; + CANVAS.lineWidth = 1; +} +Drawing.prototype.loadTextures = function(textures){ TEXTURES = textures; } +Drawing.prototype.setFillColor = function(r,g,b){ CANVAS.fillStyle = "rgb("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+")"; } +Drawing.prototype.setFillColorA = function(r,g,b,a){ CANVAS.fillStyle = "rgba("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+", "+(a>255?1:(a<0?0:a/255))+")"; } +Drawing.prototype.setLineColor = function(r,g,b){ CANVAS.strokeStyle = "rgb("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+")"; } +Drawing.prototype.setLineColorA = function(r,g,b,a){ CANVAS.strokeStyle = "rgba("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+", "+(a>255?1:(a<0?0:a/255))+")"; } +Drawing.prototype.clipCircle = function(centerx,centery,radius){ CANVAS.beginPath(); CANVAS.arc(centerx,centery,radius,0,6.28318531,false); CANVAS.clip(); } +Drawing.prototype.clipRectangle = function(x1,y1,x2,y2){ CANVAS.beginPath(); CANVAS.strokeRect(x1,y1,x2-x1,y2-y1); CANVAS.clip(); } +Drawing.prototype.drawCircle = function(centerx,centery,radius,style){ + CANVAS.beginPath(); + CANVAS.arc(centerx, centery, radius, 0, Math.PI*2, false); + if(style & this.FILL) CANVAS.fill(); + if(style & this.WIREFRAME) CANVAS.stroke(); +} +Drawing.prototype.drawImage = function(x1,y1,x2,y2,img,angle){ + if(img.complete){ + x1|=0; + y1|=0; + x2|=0; + y2|=0; + if(x2>1; + var centery = (y1+y2)>>1; + + CANVAS.save(); + CANVAS.translate(centerx, centery); + if(angle) CANVAS.rotate(angle*0.01745329); + CANVAS.drawImage(img, x1-centerx, y1-centery, x2-x1, y2-y1); + CANVAS.restore(); + } +} +Drawing.prototype.drawLine = function(x1, y1, x2, y2){ CANVAS.beginPath(); CANVAS.moveTo(x1|0, y1|0); CANVAS.lineTo(x2|0, y2|0); CANVAS.stroke(); } +Drawing.prototype.drawRectangle = function(x1, y1, x2, y2, style, angle){ + x1|=0; + y1|=0; + x2|=0; + y2|=0; + + if(!angle){ + if(style & this.FILL) CANVAS.fillRect(x1, y1, x2-x1, y2-y1); + if(style & this.WIREFRAME) CANVAS.strokeRect(x1, y1, x2-x1, y2-y1); + }else{ + var centerx = (x1+x2)>>1; var centery = (y1+y2)>>1; + + CANVAS.save(); + CANVAS.translate(centerx, centery); + CANVAS.rotate(angle*DEGTORAD); + if(style & this.FILL) CANVAS.fillRect(x1-centerx, y1-centery, x2-x1, y2-y1); + if(style & this.WIREFRAME) CANVAS.strokeRect(x1-centerx, y1-centery, x2-x1, y2-y1); + CANVAS.restore(); + } +} +Drawing.prototype.drawScene = function(array,style){ + var piOver2 = 1.570796326794897; + var piOver4 = 0.785398163397448; + var sqrt2half = 1.414213562373095; + + for(tri=array.length;--tri>=0;){ + var x1 = array[tri][0]; + var y1 = array[tri][1]; + var x2 = array[tri][2]; + var y2 = array[tri][3]; + var x3 = array[tri][4]; + var y3 = array[tri][5]; + shade=array[tri][10]; + + if(TEXTURES && array[tri][9]>=0){ + CANVAS.save(); + + var u = (x2-x3)*(x2-x3)+(y2-y3)*(y2-y3); + var v = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3); + var w = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1); + + var canvasRot = 0.5*Math.acos((w+v-u)/(2*Math.sqrt(w*v))); + var scale = Math.cos(canvasRot)*sqrt2half; + + CANVAS.translate(x1,y1); + CANVAS.rotate(Math.atan2(y2-y1,x2-x1)-piOver2+canvasRot); + CANVAS.scale(Math.tan(canvasRot),1); + CANVAS.rotate(piOver4); + CANVAS.scale(Math.sqrt(w)*scale,Math.sqrt(v)*scale); + //CANVAS.transform(x2-x1,y2-y1,x3-x1,y3-y1, x1,y1); + CANVAS.drawImage((canvasimg = TEXTURES[array[tri][9]]), 0,0, canvasimg.width,canvasimg.height, 0,0, 1,1); + CANVAS.restore(); + + if(shade!=0){ + CANVAS.beginPath(); + CANVAS.moveTo(x1,y1); + CANVAS.lineTo(x2,y2); + CANVAS.lineTo(x3,y3); + CANVAS.lineTo(x1,y1); + if(shade>0){ + if(shade>1) shade=1; + CANVAS.fillStyle = "rgba(255,255,255,"+(shade)+")"; + CANVAS.strokeStyle = "rgba(255,255,255,"+(shade*.5)+")"; + }else if(shade<0){ + if(shade<-1) shade=-1; + CANVAS.fillStyle = "rgba(0,0,0,"+(-shade)+")"; + CANVAS.strokeStyle = "rgba(0,0,0,"+(-shade*.5)+")"; + } + if(style & this.FILL) CANVAS.fill(); + if(style & this.WIREFRAME) CANVAS.stroke(); + } + }else{ + var red = array[tri][6]; + var green = array[tri][7]; + var blue = array[tri][8]; + if(shade!=0){ + red=(red*=++shade)>255?255:(red<0?0:red); + green=(green*=shade)>255?255:(green<0?0:green); + blue=(blue*=shade)>255?255:(blue<0?0:blue); + } + var color = "rgb("+(red|0)+","+(green|0)+","+(blue|0)+")"; + CANVAS.beginPath(); + CANVAS.moveTo(x1,y1); + CANVAS.lineTo(x2,y2); + CANVAS.lineTo(x3,y3); + CANVAS.lineTo(x1,y1); + if(style & this.FILL){ CANVAS.fillStyle = color; CANVAS.fill(); } + if(style & this.WIREFRAME){ CANVAS.strokeStyle = color; CANVAS.stroke(); } + } + } +} + +Drawing.prototype.drawFloor = function(x1,x2,y1,x3,x4,y2,img){ + if((x2|=0)==(x1|=0)) x2++; + if((y2|=0)==(y1|=0)) y2++; + if((x4|=0)==(x3|=0)) x4++; + var absdy=(dy = y2-y1)<0?-dy:dy; + + var sourceD = img.width-1, sourceY = (img.height-1)*(dx2 = x4-x3)/dy; + var destX = (x3-x1)/dy; + var tempY = 0; + var destW2 = (dx1 = x2-x1); + + var absscale = (fullscale = 1.5*(dy>>31?-1:1)+dy/img.height)>>31?-(fullscale-1):(fullscale+1); + var destwfullscale = fullscale*(dx2-dx1+1)/dy; + + while(tempY<0?-tempY:tempY<=absdy){ + CANVAS.drawImage(img, 0, sourceY*tempY/destW2, sourceD, 1, x1+destX*tempY, tempY+y1, destW2, absscale); + tempY+=fullscale; + destW2+=destwfullscale; + } +} +Drawing.prototype.drawWall = function(x1,y1,y2,x2,y3,y4,img){ + if(x2==x1) x2++; + if(y2==y1) y2++; + if(y4==y3) y4++; + var dx = x2-x1, dy1 = y2-y1, dy2 = y4-y3; + var absdx=dx<0?-dx:dx; + + var sourceH = img.height-1, sourceX = (img.width-1)*dy2/dx; + var destY = (y3-y1)/dx; + var tempX = 0; + + var fullscale = 1.5*(dx<0?-1:1)+dx/img.width; + var absscale = fullscale<0?(-fullscale-1):(fullscale+1); + var desthfullscale = fullscale*(dy2-dy1+1)/dx; + + while(tempX<0?-tempX:tempX<=absdx){ + CANVAS.drawImage(img, sourceX*tempX/dy1, 0, 1, sourceH, tempX+x1, y1+destY*tempX, absscale, dy1); + tempX+=fullscale; + dy1+=desthfullscale; + } +} +Drawing.prototype.zoom = function(zoom,width,height){ + ZOOM = zoom; + CANVAS.translate(width>>1, height>>1); + CANVAS.scale(ZOOM, ZOOM); + CANVAS.translate(-width>>1, -height>>1); +} +Drawing.prototype.unZoom = function(width,height){ + CANVAS.translate(width>>1, height>>1); + CANVAS.scale(1/ZOOM, 1/ZOOM); + CANVAS.translate(-width>>1, -height>>1); + ZOOM = 1; +} +Drawing.prototype.clear = function(x1, y1, x2, y2){ CANVAS.clearRect(x1, y1, x2-x1, y2-y1); } + +Draw = new Drawing(); \ No newline at end of file diff --git a/src/plugins/cordova-plugin-device-motion/sim-host-handlers.js b/src/plugins/cordova-plugin-device-motion/sim-host-handlers.js new file mode 100644 index 00000000..d9464d70 --- /dev/null +++ b/src/plugins/cordova-plugin-device-motion/sim-host-handlers.js @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +var deviceMotion = require('cordova-plugin-device-motion'); +var accelerometerHandle = null; + +module.exports = { + 'Accelerometer': { + start: function (win, lose) { + accelerometerHandle = setInterval(function() { + win(getCurrentAcceleration()); + }, deviceMotion.ACCELEROMETER_REPORT_INTERVAL); + }, + stop: function (win, lose) { + if (accelerometerHandle === null) { + return; + } + + clearInterval(accelerometerHandle); + accelerometerHandle = null; + }, + getCurrentAcceleration: function (win, lose) { + win(getCurrentAcceleration()); + } + } +}; + +function getCurrentAcceleration () { + return { + x: parseFloat(deviceMotion.x), + y: parseFloat(deviceMotion.y), + z: parseFloat(deviceMotion.z), + timestamp: (new Date()).getTime() + }; +} diff --git a/src/plugins/cordova-plugin-device-motion/sim-host-panels.html b/src/plugins/cordova-plugin-device-motion/sim-host-panels.html new file mode 100644 index 00000000..e4bae7cc --- /dev/null +++ b/src/plugins/cordova-plugin-device-motion/sim-host-panels.html @@ -0,0 +1,35 @@ + + + + + + + + + + + Click and drag with the mouse to manipulate the device.
Hold the Shift key to modify 'alpha'
+
+ + + + + + + + + + Play + +
diff --git a/src/plugins/cordova-plugin-device-motion/sim-host.js b/src/plugins/cordova-plugin-device-motion/sim-host.js new file mode 100644 index 00000000..0557b5cc --- /dev/null +++ b/src/plugins/cordova-plugin-device-motion/sim-host.js @@ -0,0 +1,279 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +// https://github.com/apache/cordova-plugin-device-motion/ + +require('./3d'); +require('./draw'); + +var axisX, + axisY, + axisZ, + alpha, + beta, + gamma; + +var defaultXAxis = 100, + defaultYAxis = 80; + +var _mouseDown, + _shiftKeyDown = false, + _offsets, + _oldX, + _oldY, + _oldAlphaX, + _deltaAlpha, + _alpha, + _beta, + _gamma, + _shape = + // + // The front side + // + // x, y, z x, y, z x, y, z + // for some strange reason for y -100 is top, 100 is bottom + '-30,30,10, 30,30,10, 30,60,10, 100,100,100,-1,0;' + // top left, top right, bottom right - of the right triangle + '-30,30,10, 30,60,10, -30,60,10, 100,100,100,-1,0;' + // top left, right bottom, left bottom - of the left triangle + // front side 'the phone display' + '-20,-50,11, 20,-50,11, 20,20,11, 100,100,100,-1,0;' + + '-20,-50,11, 20,20,11, -20,20,11, 100,100,100,-1,0;' + + // below the display + '-30,30,10, 30,20,10, 30,30,10, 0,0,0,-1,0;' + + '-30,30,10, -30,20,10, 30,20,10, 0,0,0,-1,0;' + + // above the display + '-30,-60,10, 30,-60,10, 30,-50,10, 0,0,0,-1,0;' + + '-30,-60,10, 30,-50,10, -30,-50,10, 0,0,0,-1,0;' + + // left of the display + '-30,-50,10, -20,-50,10, -20,20,10, 0,0,0,-1,0;' + + '-30,-50,10, -20,20,10, -30,20,10, 0,0,0,-1,0;' + + // right of the display + '20,-50,10, 30,-50,10, 30,20,10, 0,0,0,-1,0;' + + '20,-50,10, 30,20,10, 20,20,10, 0,0,0,-1,0;' + + + + // back side, opposite side to the above one + '-30,-60,-10, 30,60,-10, 30,-60,-10, 0,0,0,-1,0;' + + '-30,-60,-10, -30,60,-10, 30,60,-10, 0,00,-1,0;' + + // right side + '30,-60,-10, 30,60,-10, 30,60,10, 50,50,80,-1,0;' + + '30,-60,-10, 30,60,10, 30,-60,10, 50,50,80,-1,0;' + + // left side + '-30,-60,-10, -30,60,10, -30,60,-10, 50,50,80,-1,0;' + + '-30,-60,-10, -30,-60,10, -30,60,10, 50,50,80,-1,0;' + + + // top + '30,-60,-10, -30,-60,10, -30,-60,-10, 50,80,50,-1,0;' + + '30,-60,-10, 30,-60,10, -30,-60,10, 50,80,50,-1,0;' + + // bottom + '30,60,-10, -30,60,-10, -30,60,10, 80,50,50,-1,0;' + + '30,60,-10, -30,60,10, 30,60,10, 80,50,50,-1,0'; + + +// report interval in milliseconds +var ACCELEROMETER_REPORT_INTERVAL = 50; + +var gConstant = 9.81; + +var recordedGestures = [ + { + name: 'Shake', + fn: shake + } +]; + +function initialize() { + axisX = document.getElementById('accel-x'); + axisY = document.getElementById('accel-y'); + axisZ = document.getElementById('accel-z'); + alpha = document.getElementById('accel-alpha'); + beta = document.getElementById('accel-beta'); + gamma = document.getElementById('accel-gamma'); + + createCanvas(); + + setToDefaultPosition(); + + var recordedGesturesList = document.getElementById('accel-recorded-data'); + recordedGestures.forEach(function (gesture) { + var option = document.createElement('option'); + option.appendChild( document.createTextNode(gesture.name)); + recordedGesturesList.appendChild(option); + }); + + document.getElementById('accel-play-recorded').addEventListener('click', function() { + var list = document.getElementById('accel-recorded-data'); + recordedGestures[list.selectedIndex].fn(); + }); +} + +function setToDefaultPosition() { + var accel = {x: 0, y: 0, z: -1, alpha: 0, beta: 0, gamma: 0 }; + + axisX.value = (accel.x * gConstant).toFixed(2); + axisY.value = (accel.y * gConstant).toFixed(2); + axisZ.value = (accel.z * gConstant).toFixed(2); + + _alpha = accel.alpha; + _beta = accel.beta; + _gamma = accel.gamma; + _deltaAlpha = 360; + + _oldX = 0; + _oldY = 0; + _oldAlphaX = 0; + _offsets = { + x: accel.x, + y: accel.y, + z: accel.z + }; + + updateCanvas(0,0); +} + +function shake() { + var id, + count = 1, + stopCount = 2500 / ACCELEROMETER_REPORT_INTERVAL, + oldX = axisX.value; + + id = setInterval(function () { + var freq = 1, + amp = 20, + value = Math.round(amp * Math.sin(freq * count * (180 / Math.PI)) * 100) / 100; + + if (count > stopCount) { + updateCanvasCenter(defaultXAxis, defaultYAxis); + axisX.value = oldX; + clearInterval(id); + return; + } + + axisX.value = (value * gConstant).toFixed(2); + // shake effect + var center = Math.random() * 10 + (defaultXAxis - 5); + updateCanvasCenter(center, defaultYAxis); + count++; + }, ACCELEROMETER_REPORT_INTERVAL); + } + +module.exports = { + initialize: initialize, + ACCELEROMETER_REPORT_INTERVAL: ACCELEROMETER_REPORT_INTERVAL, + get x() { + return parseFloat(axisX.value); + }, + get y() { + return parseFloat(axisY.value); + }, + get z() { + return parseFloat(axisZ.value); + } +}; + +function updateCanvasCenter(xAxis, yAxis) { + ThreeDee.setCenter(xAxis, yAxis); + Draw.initialize(document.getElementById('accelerometer-canvas')); + Draw.clear(0, 0, 480, 300); + Draw.drawScene(ThreeDee.getTranslation(), 3); +} + +function updateCanvas(a, b, g) { + ThreeDee.loadMesh(_shape); + g = g || 0; + ThreeDee.rotate(0, g, 0); + ThreeDee.rotate(b, 0, a); + ThreeDee.backface(); + ThreeDee.shade(); + ThreeDee.zSort(); + Draw.initialize(document.getElementById('accelerometer-canvas')); + Draw.clear(0, 0, 480, 300); + Draw.drawScene(ThreeDee.getTranslation(), 3); +} + +function createCanvas() { + var node = document.getElementById('accelerometer-canvas'), + cosX, sinX, cosY, sinY; + + ThreeDee.setCenter(defaultXAxis, defaultYAxis); + ThreeDee.setLight(-300, -300, 800); + + node.addEventListener('mousemove', function (e) { + if (_mouseDown && !_shiftKeyDown) { + _offsets.x = (_offsets.x + _oldX - e.offsetX) % 360; + _offsets.y = (_offsets.y + _oldY - e.offsetY) % 360; + + _alpha = _alpha || 0; + + // enforce gamma in [-90,90] as per w3c spec + _gamma = -_offsets.x; + if (_gamma < -90) { + _gamma = -90; + } + if (_gamma > 90) { + _gamma = 90; + } + + // enforce beta in [-180,180] as per w3c spec + _beta = -_offsets.y % 360; + if (_beta < -180) { + _beta += 360; + } + else if (_beta >= 180) { + _beta -= 360; + } + + cosX = Math.cos((_gamma) * (Math.PI / 180)); + sinX = Math.sin((_gamma) * (Math.PI / 180)); + cosY = Math.cos((_beta) * (Math.PI / 180)); + sinY = Math.sin((_beta) * (Math.PI / 180)); + + axisX.value = (cosY * sinX * gConstant).toFixed(2); + axisY.value = (-sinY * gConstant).toFixed(2); + axisZ.value = (-cosY * cosX * gConstant).toFixed(2); + beta.value = _beta; + gamma.value = _gamma; + + + } else if (_mouseDown && _shiftKeyDown) { + _deltaAlpha = (_deltaAlpha - (_oldAlphaX - e.offsetX) * 2.5) % 360; + _alpha = (360 - _deltaAlpha) % 360; + + alpha.value = _alpha; + } + + _oldX = e.offsetX; + _oldY = e.offsetY; + _oldAlphaX = e.offsetX; + + updateCanvas(_deltaAlpha, -_beta, _gamma); + }); + + node.addEventListener('mousedown', function (e) { + _oldX = e.offsetX; + _oldY = e.offsetY; + _mouseDown = true; + }); + + node.addEventListener('mouseup', function () { + _mouseDown = false; + }); + + document.addEventListener('mouseup', function () { + //Catch mouseup events that fire when outside canvas bounds + _mouseDown = false; + }); + + document.addEventListener('keydown', function (e) { + if (e.keyCode === 16) { // Shift Key + _oldAlphaX = _oldX; + _shiftKeyDown = true; + } + }); + + document.addEventListener('keyup', function (e) { + if (e.keyCode === 16) { // Shift Key + _shiftKeyDown = false; + } + }); + + return node; +} diff --git a/src/plugins/cordova-plugin-device/sim-host-handlers.js b/src/plugins/cordova-plugin-device/sim-host-handlers.js new file mode 100644 index 00000000..f73327aa --- /dev/null +++ b/src/plugins/cordova-plugin-device/sim-host-handlers.js @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = { + 'Device': { + 'getDeviceInfo': function (success, fail, args) { + success({ + model: document.getElementById('device-model').value, + platform: document.getElementById('device-platform').value, + uuid: document.getElementById('device-uuid').value, + version: document.getElementById('device-version').value + }); + } + } +}; diff --git a/src/plugins/cordova-plugin-device/sim-host-panels.html b/src/plugins/cordova-plugin-device/sim-host-panels.html new file mode 100644 index 00000000..d9ef21f3 --- /dev/null +++ b/src/plugins/cordova-plugin-device/sim-host-panels.html @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/plugins/cordova-plugin-device/sim-host.js b/src/plugins/cordova-plugin-device/sim-host.js new file mode 100644 index 00000000..8866b9b9 --- /dev/null +++ b/src/plugins/cordova-plugin-device/sim-host.js @@ -0,0 +1,314 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +function initialize() { + var devices = [ + { + 'id': 'AcerA500', + 'name': 'Acer A500', + 'model': 'Picasso', + 'platform': 'Android', + 'version': '4.0', + 'uuid': '500' + }, + { + 'id': 'Bold9700', + 'name': 'BlackBerry Bold 9700', + 'model': '9700', + 'platform': 'BlackBerry OS', + 'version': '6', + 'uuid': '42' + }, + { + 'id': 'Bold9900', + 'name': 'BlackBerry Bold 9900', + 'model': '9900', + 'platform': 'BlackBerry OS', + 'version': '7', + 'uuid': '42' + }, + { + 'id': 'Curve9300', + 'name': 'BlackBerry Curve 9300', + 'model': '9300', + 'platform': 'BlackBerry OS', + 'version': '6', + 'uuid': '42' + }, + { + 'id': 'Curve9350-9360-9370', + 'name': 'BlackBerry Curve 9350/9360/9370', + 'model': '9350-9360-9370', + 'platform': 'BlackBerry OS', + 'version': '7', + 'uuid': '42' + }, + { + 'id': 'FWVGA', + 'name': 'Generic - FWVGA (480x854)', + 'model': 'Generic', + 'platform': 'Generic', + 'version': 'Generic', + 'uuid': '42' + }, + { + 'id': 'G1', + 'name': 'HTC G1', + 'model': 'G1', + 'platform': 'Android', + 'version': '1.6', + 'uuid': '6F196F23-FD0D-4F62-B27B-730147FCC5A3' + }, + {'id': 'HPPre3', 'name': 'HP Pre 3', 'model': 'Pre', 'platform': 'WebOS', 'version': '2.x'}, + {'id': 'HPVeer', 'name': 'HP Veer', 'model': 'Veer', 'platform': 'WebOS', 'version': '2.x'}, + { + 'id': 'HVGA', + 'name': 'Generic - HVGA (320x480)', + 'model': 'Generic', + 'platform': 'Generic', + 'version': 'Generic', + 'uuid': '42' + }, + { + 'id': 'iPad', + 'name': 'iPad', + 'model': 'iPad', + 'platform': 'iOS', + 'version': '1.6', + 'uuid': 'e0101010d38bde8e6740011221af335301010333' + }, + { + 'id': 'iPad3', + 'name': 'iPad 3', + 'model': 'iPad3', + 'platform': 'iOS', + 'version': '5', + 'uuid': 'e0101010d38bde8e6740011221af335301010334' + }, + { + 'id': 'iPhone3', + 'name': 'iPhone 3G/3Gs', + 'model': '3G', + 'platform': 'iPhone', + 'version': '3', + 'uuid': 'e0101010d38bde8e6740011221af335301010333' + }, + { + 'id': 'iPhone4', + 'name': 'iPhone 4/4s', + 'model': '4s', + 'platform': 'iOS', + 'version': '5', + 'uuid': 'e0101010d38bde8e6740011221af335301010333' + }, + { + 'id': 'iPhone5', + 'name': 'iPhone 5', + 'model': '5', + 'platform': 'iOS', + 'version': '6', + 'uuid': 'e0101010d38bde8e6740011221af335301010333' + }, + { + 'id': 'Legend', + 'name': 'HTC Legend', + 'model': 'Legend', + 'platform': 'Android', + 'version': '1.6', + 'uuid': '6F196F23-FD0D-4F62-B27B-730147FCC5A3' + }, + { + 'id': 'Nexus', + 'name': 'Nexus One', + 'model': 'Nexux One', + 'platform': 'Android', + 'version': '2.x.x', + 'uuid': '6F196F23-FD0D-4F62-B27B-730147FCC5A3' + }, + { + 'id': 'Nexus4', + 'name': 'Nexus 4', + 'model': 'Nexus 4', + 'platform': 'Android', + 'version': '4.2.x', + 'uuid': 'DC46B660-EF6F-46D4-AC24-85CFAB0C7694' + }, + { + 'id': 'Nexus7', + 'name': 'Nexus 7 (Tablet)', + 'model': 'Nexus 7 8/16 GB', + 'platform': 'Android', + 'version': '4.x.x', + 'uuid': '903802EA-1786-4175-B0F1-1FDF87813CAA' + }, + { + 'id': 'NexusGalaxy', + 'name': 'Nexus (Galaxy)', + 'model': 'Galaxy Nexus (generic)', + 'platform': 'Android', + 'version': '4.x.x', + 'uuid': '3D0AD03B-8B46-431A-BEF5-FF01B96BA990' + }, + { + 'id': 'NexusS', + 'name': 'Nexus S', + 'model': 'Nexux S', + 'platform': 'Android', + 'version': '2.3.x', + 'uuid': 'F54E13F1-C1B7-4212-BFA8-AB3C9C3F088F' + }, + {'id': 'NokiaN8', 'name': 'Nokia N8', 'model': 'N8', 'platform': 'SymbianOS', 'version': '3', 'uuid': '42'}, + { + 'id': 'NokiaN97', + 'name': 'Nokia N97/5800 (touch)', + 'model': 'N97', + 'platform': 'S60', + 'version': 'v5', + 'uuid': '42' + }, + {'id': 'PalmPre', 'name': 'Palm Pre', 'model': 'Pre', 'platform': 'WebOS', 'version': '1.x'}, + {'id': 'PalmPre2', 'name': 'Palm Pre 2', 'model': 'Pre', 'platform': 'WebOS', 'version': '2.x'}, + { + 'id': 'Pearl9100', + 'name': 'BlackBerry Pearl 9100', + 'model': '9100', + 'platform': 'BlackBerry OS', + 'version': '6', + 'uuid': '42' + }, + { + 'id': 'Playbook', + 'name': 'BlackBerry Playbook', + 'model': '100669958', + 'platform': 'BlackBerry PlayBook OS', + 'version': 'BlackBerry PlayBook OS', + 'uuid': '42' + }, + { + 'id': 'Q10', + 'name': 'BlackBerry Q10', + 'model': 'Q10', + 'platform': 'BlackBerry', + 'version': '10.1', + 'uuid': '42' + }, + { + 'id': 'QVGA', + 'name': 'Generic - QVGA (240X320)', + 'model': 'Generic', + 'platform': 'Generic', + 'version': 'Generic', + 'uuid': '42' + }, + { + 'id': 'Style9670', + 'name': 'BlackBerry Style 9670', + 'model': '9670', + 'platform': 'BlackBerry OS', + 'version': '6', + 'uuid': '42' + }, + { + 'id': 'Tattoo', + 'name': 'HTC Tattoo', + 'model': 'Tattoo', + 'platform': 'Android', + 'version': '1.6', + 'uuid': '6F196F23-FD0D-4F62-B27B-730147FCC5A3' + }, + { + 'id': 'Torch9800', + 'name': 'BlackBerry Torch 9800', + 'model': '9800', + 'platform': 'BlackBerry OS', + 'version': '6', + 'uuid': '42' + }, + { + 'id': 'Torch9810', + 'name': 'BlackBerry Torch 9810', + 'model': '9810', + 'platform': 'BlackBerry OS', + 'version': '7', + 'uuid': '42' + }, + { + 'id': 'Torch9860-9850', + 'name': 'BlackBerry Torch 9860/9850', + 'model': '9860-9850', + 'platform': 'BlackBerry OS', + 'version': '7', + 'uuid': '42' + }, + {'id': 'Wave', 'name': 'Samsung Wave', 'model': 'Wave', 'platform': 'Bada', 'version': 'n/a'}, + { + 'id': 'WQVGA', + 'name': 'Generic - WQVGA (240x480)', + 'model': 'Generic', + 'platform': 'Generic', + 'version': 'Generic', + 'uuid': '42' + }, + { + 'id': 'WVGA', + 'name': 'Generic - WVGA (480x800)', + 'model': 'Generic', + 'platform': 'Generic', + 'version': 'Generic', + 'uuid': '42' + }, + { + 'id': 'Z10', + 'name': 'BlackBerry Z10', + 'model': 'Z10', + 'platform': 'BlackBerry', + 'version': '10.0.10', + 'uuid': '42' + } + ]; + + devices.sort(function (left, right) { + left = left.name.toUpperCase(); + right = right.name.toUpperCase(); + if (left < right) { + return -1; + } + if (right < left) { + return 1; + } + return 0; + }); + + var deviceList = document.getElementById('device-list'); + + devices.forEach(function (device) { + var option = document.createElement('option'); + option.value = device.id; + + var caption = document.createTextNode(device.name); + option.appendChild(caption); + + option.setAttribute('_model', device.model); + option.setAttribute('_platform', device.platform); + option.setAttribute('_version', device.version); + option.setAttribute('_uuid', device.uuid); + + deviceList.appendChild(option); + }); + + deviceList.onchange = handleSelectDevice; + deviceList.value = 'WVGA'; + handleSelectDevice(); +} + +function handleSelectDevice() { + var deviceList = document.getElementById('device-list'); + var option = deviceList.options[deviceList.selectedIndex]; + document.getElementById('device-model').value = option.getAttribute('_model'); + document.getElementById('device-platform').value = option.getAttribute('_platform'); + document.getElementById('device-uuid').value = option.getAttribute('_uuid'); + document.getElementById('device-version').value = option.getAttribute('_version'); +} + +module.exports = { + initialize: initialize +}; diff --git a/src/plugins/cordova-plugin-dialogs/app-host.js b/src/plugins/cordova-plugin-dialogs/app-host.js new file mode 100644 index 00000000..dc50aabf --- /dev/null +++ b/src/plugins/cordova-plugin-dialogs/app-host.js @@ -0,0 +1,156 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +// https://github.com/apache/cordova-plugin-dialogs/ + +module.exports = function (messages) { + messages.register('alert', function (event, callback) { + var args = event; + var title = args[1]; + var text = args[0]; + var buttonName = args[2]; + createDialog(title, text, [buttonName], false, null, callback); + }); + + messages.register('confirm', function (event, callback) { + var args = event; + var title = args[1]; + var text = args[0]; + var buttons = args[2]; + createDialog(title, text, buttons, false, null, callback); + }); + + messages.register('prompt', function (event, callback) { + var args = event; + var title = args[1]; + var text = args[0]; + var buttons = args[2]; + var defaultText = args[3]; + createDialog(title, text, buttons, true, defaultText, callback); + }); + + messages.register('beep', function (event, callback) { + var times = event; + for (var i = 0; i < times; i++) { + // 1700ms below is the beep sound duration + setTimeout(makeBeep, 1700 * i); + } + // call callback when beep(s) is done + setTimeout(callback, 1700 * times); + }); + + function makeBeep() { + var audio = document.createElement('audio'); + audio.src = 'data:audio/wav;base64,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'; + audio.play(); + } + + function createDialog (title, message, buttons, addInput, defaultText, callback) { + var dlgWrap = document.createElement('div'); + dlgWrap.style.position = 'absolute'; + dlgWrap.style.width = '100%'; + dlgWrap.style.height = '100%'; + dlgWrap.style.backgroundColor = 'rgba(0,0,0,0.25)'; + dlgWrap.style.zIndex = '100000'; + dlgWrap.style.top = '0'; + dlgWrap.style.left = '0'; + dlgWrap.style.margin = '0'; + dlgWrap.style.padding = '0'; + + var dlg = document.createElement('div'); + dlg.style.height = 'auto'; + dlg.style.overflow = 'auto'; + dlg.style.backgroundColor = 'white'; + dlg.style.position = 'relative'; + dlg.style.lineHeight = '2'; + + dlg.style.top = '50%'; // center vertically + dlg.style.transform = 'translateY(-50%)'; + dlg.style.margin = '0px 30%'; + dlg.style.padding = '10px'; + dlg.style.boxShadow = '2px 2px 5px 1px rgba(0, 0, 0, 0.2)'; + dlg.style.borderRadius = '2px'; + + var titleStyle = 'border-top-left-radius: 2px; border-top-right-radius: 2px; position: relative; background-color: #03a9f4; color: #fff; font-size: 16px; padding: 7px 10px; height: 24px; text-transform: none; font-family: \'Helvetica Neue\', \'Roboto\', \'Segoe UI\', \'sans-serif\'; line-height: 24px;'; + // needed to remove white line at the top of the title container + if (addInput) { + titleStyle += 'margin: -11px -10px -10px;'; + } else { + titleStyle += 'margin: -10px;'; + } + + // dialog layout template + var dlgHtml = '
' + + '
'; + + if (addInput) { + dlgHtml += ''; + } + dlg.innerHTML = dlgHtml; + + dlg.querySelector('#lbl-title').appendChild(document.createTextNode(title)); + dlg.querySelector('#lbl-message').appendChild(document.createTextNode(message)); + if (addInput) { + dlg.querySelector('#prompt-input').setAttribute('placeholder', defaultText); + } + + function makeButtonCallback(idx) { + return function () { + var value; + if (addInput) { + value = dlg.querySelector('#prompt-input').value; + } + + dlgWrap.parentNode.removeChild(dlgWrap); + + if (callback) { + if (addInput) { + callback(false, { input1: value, buttonIndex: idx }); + } else { + callback(false, idx); + } + } + }; + } + + function addButton(idx, label) { + var button = document.createElement('button'); + button.style.float = 'right'; + button.style.minWidth = '112px'; + button.style.display = 'inline-block'; + button.style.textAlign = 'center'; + button.style.zoom = '1'; + button.style.fontFamily = '\'Helvetica Neue\', \'Roboto\', \'Segoe UI\', \'sans-serif\''; + button.style.overflow = 'visible'; + button.style.border = '1px solid #d3d3d3'; + button.style.background = '#e6e6e6'; + button.style.fontWeight = 'normal'; + button.style.color = '#555'; + button.style.margin = '10px 0 10px 10px'; + button.style.cursor = 'pointer'; + button.style.fontSize = '14px'; + button.style.minHeight = '30px'; + button.tabIndex = idx; + button.onclick = makeButtonCallback(idx + 1); + button.appendChild(document.createTextNode(label)); + dlg.appendChild(button); + } + + // reverse order is used since we align buttons to the right + for (var idx = buttons.length - 1; idx >= 0; idx--) { + addButton(idx, buttons[idx]); + } + + dlgWrap.appendChild(dlg); + document.body.appendChild(dlgWrap); + + // make sure input field is under focus + if (addInput) { + setTimeout(function() { + dlg.querySelector('#prompt-input').focus(); + }); + } + + return dlgWrap; + } +}; diff --git a/src/plugins/cordova-plugin-dialogs/sim-host-handlers.js b/src/plugins/cordova-plugin-dialogs/sim-host-handlers.js new file mode 100644 index 00000000..9a18e43c --- /dev/null +++ b/src/plugins/cordova-plugin-dialogs/sim-host-handlers.js @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +// https://github.com/apache/cordova-plugin-dialogs/ + +module.exports = function (messages) { + function alert (success, fail, args) { + messages.call('alert', args).then(function () { + success(); + }, function (err) { + fail(err); + }); + } + + function confirm (success, fail, args) { + messages.call('confirm', args).then(function (result) { + success(result); + }, function (err) { + fail(err); + }); + } + + function prompt (success, fail, args) { + messages.call('prompt', args).then(function (result) { + success(result); + }, function (err) { + fail(err); + }); + } + + function beep (success, fail, args) { + var times = args[0]; + messages.call('beep', times).then(function () { + success(); + }, function (err) { + fail(err); + }); + } + + return { + Notification: { + alert: alert, + confirm: confirm, + prompt: prompt, + beep: beep, + } + }; +}; diff --git a/src/plugins/cordova-plugin-file/MyFile.js b/src/plugins/cordova-plugin-file/MyFile.js new file mode 100644 index 00000000..b9d0dc47 --- /dev/null +++ b/src/plugins/cordova-plugin-file/MyFile.js @@ -0,0 +1,42 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +/** + * Interface to wrap the native File interface. + * + * This interface is necessary for creating zero-length (empty) files, + * something the Filesystem API allows you to do. Unfortunately, File's + * constructor cannot be called directly, making it impossible to instantiate + * an empty File in JS. + * + * @param {Object} opts Initial values. + * @constructor + */ +function MyFile(opts) { + var blob_ = new Blob(); + + this.size = opts.size || 0; + this.name = opts.name || ''; + this.type = opts.type || ''; + this.lastModifiedDate = opts.lastModifiedDate || null; + this.storagePath = opts.storagePath || ''; + + // Need some black magic to correct the object's size/name/type based on the + // blob that is saved. + Object.defineProperty(this, 'blob_', { + enumerable: true, + get: function() { + return blob_; + }, + set: function(val) { + blob_ = val; + this.size = blob_.size; + this.name = blob_.name; + this.type = blob_.type; + this.lastModifiedDate = blob_.lastModifiedDate; + }.bind(this) + }); +} + +MyFile.prototype.constructor = MyFile; + +module.exports = MyFile; diff --git a/src/plugins/cordova-plugin-file/app-host-clobbers.js b/src/plugins/cordova-plugin-file/app-host-clobbers.js new file mode 100644 index 00000000..0173b012 --- /dev/null +++ b/src/plugins/cordova-plugin-file/app-host-clobbers.js @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = { + // This variable is required on Windows so that plugin works + Windows: { + Storage: { + StorageFolder: { + getFolderFromPathAsync: function () {} + }, + StorageFile: { + getFileFromPathAsync: function () {} + }, + ApplicationData: { + current: { + localFolder: { + path: '' + }, + temporaryFolder: { + path: '' + } + } + } + } + } +}; diff --git a/src/plugins/cordova-plugin-file/app-host-handlers.js b/src/plugins/cordova-plugin-file/app-host-handlers.js new file mode 100644 index 00000000..884160b8 --- /dev/null +++ b/src/plugins/cordova-plugin-file/app-host-handlers.js @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +module.exports = function (messages) { + var isWebkit = window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL; + + return isWebkit ? require('./app-host-webkit-handlers') : require('./app-host-non-webkit-handlers'); +}; diff --git a/src/plugins/cordova-plugin-file/app-host-non-webkit-handlers.js b/src/plugins/cordova-plugin-file/app-host-non-webkit-handlers.js new file mode 100644 index 00000000..c487feff --- /dev/null +++ b/src/plugins/cordova-plugin-file/app-host-non-webkit-handlers.js @@ -0,0 +1,785 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +if (!window.indexedDB) { + throw new Error('indexedDB not supported'); +} + +// Since we are using browser implementation +// of cordova-file-plugin for non-webkit browsers, +// we should reference MyFile, because currently loaded +// simulation platform might not be the 'browser'. +// (browser platform uses this file in its implementation). +var MyFile = require('./MyFile'); + +// Since we are using browser implementation +// of cordova-file-plugin for non-webkit browsers, +// we should reference Indexed DB, because currently loaded +// simulation platform might not be the 'browser'. +// (browser platform uses this file in its implementation). +var indexedDB = require('./indexedDB'); + +var DIR_SEPARATOR = '/'; +var FILESYSTEM_PREFIX = 'file:///'; + +var fileSystem = null; + +var pathsPrefix = { + // Read-only directory where the application is installed. + applicationDirectory: window.location.origin + '/', + // Where to put app-specific data files. + dataDirectory: 'file:///persistent/', + // Cached files that should survive app restarts. + // Apps should not rely on the OS to delete files in here. + cacheDirectory: 'file:///temporary/', + // Read-only directory where the application is installed. + // Android: the application space on external storage. + externalApplicationStorageDirectory: null, + // Android: Where to put app-specific data files on external storage. + externalDataDirectory: null, + // Android: the application cache on external storage. + externalCacheDirectory: null, + // Android: the external storage (SD card) root. + externalRootDirectory: null, + // iOS: Temp directory that the OS can clear at will. + tempDirectory: null, + // iOS: Holds app-specific files that should be synced (e.g. to iCloud). + syncedDataDirectory: null, + // iOS: Files private to the app, but that are meaningful to other applciations (e.g. Office files) + documentsDirectory: null, + // BlackBerry10: Files globally available to all apps + sharedDirectory: null +}; + +// We must override some functionality so that plugin can work properly, +// for example, we cannot call 'cordova' or file-plugin related files before deviceready +// event fired since app-host-handler's files initializes before them. +document.addEventListener('deviceready', function () { + // We must override getFs function since we are using browser implementation + // of cordova-plugin-file so everything will work as expected. + window.cordova.require('cordova-plugin-file.fileSystems').getFs = function (name, callback) { + callback(new window.FileSystem(name, fileSystem.root)); + }; + // Special functionality for proper Firefox work. + window.FileSystem.prototype.__format__ = function(fullPath) { + return (FILESYSTEM_PREFIX + this.name + (fullPath[0] === '/' ? '' : '/') + encodeURI(fullPath)); + }; +}, false); + +/*** Helpers ***/ + +// When saving an entry, the fullPath should always lead with a slash and never +// end with one (e.g. a directory). Also, resolve '.' and '..' to an absolute +// one. This method ensures path is legit! +function resolveToFullPath_(cwdFullPath, path) { + path = path || ''; + var fullPath = path; + var prefix = ''; + + cwdFullPath = cwdFullPath || DIR_SEPARATOR; + if (cwdFullPath.indexOf(FILESYSTEM_PREFIX) === 0) { + prefix = cwdFullPath.substring(0, cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length)); + cwdFullPath = cwdFullPath.substring(cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length)); + } + + var relativePath = path[0] !== DIR_SEPARATOR; + if (relativePath) { + fullPath = cwdFullPath; + if (cwdFullPath !== DIR_SEPARATOR) { + fullPath += DIR_SEPARATOR + path; + } else { + fullPath += path; + } + } + + // Remove doubled separator substrings + var re = new RegExp(DIR_SEPARATOR + DIR_SEPARATOR, 'g'); + fullPath = fullPath.replace(re, DIR_SEPARATOR); + + // Adjust '..'s by removing parent directories when '..' flows in path. + var parts = fullPath.split(DIR_SEPARATOR); + for (var i = 0; i < parts.length; ++i) { + var part = parts[i]; + if (part === '..') { + parts[i - 1] = ''; + parts[i] = ''; + } + } + fullPath = parts.filter(function(el) { + return el; + }).join(DIR_SEPARATOR); + + // Add back in leading slash. + if (fullPath[0] !== DIR_SEPARATOR) { + fullPath = DIR_SEPARATOR + fullPath; + } + + // Replace './' by current dir. ('./one/./two' -> one/two) + fullPath = fullPath.replace(/\.\//g, DIR_SEPARATOR); + + // Replace '//' with '/'. + fullPath = fullPath.replace(/\/\//g, DIR_SEPARATOR); + + // Replace '/.' with '/'. + fullPath = fullPath.replace(/\/\./g, DIR_SEPARATOR); + + // Remove '/' if it appears on the end. + if (fullPath[fullPath.length - 1] === DIR_SEPARATOR && + fullPath !== DIR_SEPARATOR) { + fullPath = fullPath.substring(0, fullPath.length - 1); + } + + var storagePath = prefix + fullPath; + storagePath = decodeURI(storagePath); + fullPath = decodeURI(fullPath); + + return { + storagePath: storagePath, + fullPath: fullPath, + fileName: fullPath.split(DIR_SEPARATOR).pop(), + fsName: prefix.split(DIR_SEPARATOR).pop() + }; +} + +function fileEntryFromIdbEntry(fileEntry) { + // IDB won't save methods, so we need re-create the FileEntry. + var clonedFileEntry = new window.FileEntry(fileEntry.name, fileEntry.fullPath, fileEntry.filesystem); + clonedFileEntry.file_ = fileEntry.file_; + + return clonedFileEntry; +} + +function readAs(what, fullPath, encoding, startPos, endPos, successCallback, errorCallback) { + getFile(function(fileEntry) { + var fileReader = new FileReader(), + blob = fileEntry.file_.blob_.slice(startPos, endPos); + + fileReader.onload = function(e) { + successCallback(e.target.result); + }; + + fileReader.onerror = errorCallback; + + switch (what) { + case 'text': + fileReader.readAsText(blob, encoding); + break; + case 'dataURL': + fileReader.readAsDataURL(blob); + break; + case 'arrayBuffer': + fileReader.readAsArrayBuffer(blob); + break; + case 'binaryString': + fileReader.readAsBinaryString(blob); + break; + } + + }, errorCallback, [fullPath, null]); +} + +/*** Handlers ***/ + +function requestFileSystem(successCallback, errorCallback, args) { + var type = args[0]; + // Size is ignored since IDB filesystem size depends + // on browser implementation and can't be set up by user + var size = args[1]; // jshint ignore: line + + if (type !== window.LocalFileSystem.TEMPORARY && type !== window.LocalFileSystem.PERSISTENT) { + errorCallback && errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + return; + } + + var name = type === window.LocalFileSystem.TEMPORARY ? 'temporary' : 'persistent'; + var storageName = (location.protocol + location.host).replace(/:/g, '_'); + + var root = new window.DirectoryEntry('', DIR_SEPARATOR); + fileSystem = new window.FileSystem(name, root); + + indexedDB.open(storageName, function() { + successCallback(fileSystem); + }, errorCallback); +} + +function requestFileSystemHandler(successCallback, errorCallback, module, event, args) { + requestFileSystem(successCallback, errorCallback, args); +} + +// list a directory's contents (files and folders). +function readEntries(successCallback, errorCallback, args) { + var fullPath = args[0]; + + if (typeof successCallback !== 'function') { + throw Error('Expected successCallback argument.'); + } + + var path = resolveToFullPath_(fullPath); + + getDirectory(function() { + indexedDB.getAllEntries(path.fullPath + DIR_SEPARATOR, path.storagePath, function(entries) { + successCallback(entries); + }, errorCallback); + }, function() { + if (errorCallback) { + errorCallback(window.FileError.NOT_FOUND_ERR); + } + }, [path.storagePath, path.fullPath, {create: false}]); +} + +function readEntriesHandler(successCallback, errorCallback, module, event, args) { + readEntries(successCallback, errorCallback, args); +} + +function getFile(successCallback, errorCallback, args) { + var fullPath = args[0]; + var path = args[1]; + var options = args[2] || {}; + + // Create an absolute path if we were handed a relative one. + path = resolveToFullPath_(fullPath, path); + + indexedDB.get(path.storagePath, function(fileEntry) { + if (options.create === true && options.exclusive === true && fileEntry) { + // If create and exclusive are both true, and the path already exists, + // getFile must fail. + + if (errorCallback) { + errorCallback(window.FileError.PATH_EXISTS_ERR); + } + } else if (options.create === true && !fileEntry) { + // If create is true, the path doesn't exist, and no other error occurs, + // getFile must create it as a zero-length file and return a corresponding + // FileEntry. + var newFileEntry = new window.FileEntry(path.fileName, path.fullPath, new window.FileSystem(path.fsName, fileSystem.root)); + + newFileEntry.file_ = new MyFile({ + size: 0, + name: newFileEntry.name, + lastModifiedDate: new Date(), + storagePath: path.storagePath + }); + + indexedDB.put(newFileEntry, path.storagePath, successCallback, errorCallback); + } else if (options.create === true && fileEntry) { + if (fileEntry.isFile) { + // Overwrite file, delete then create new. + indexedDB['delete'](path.storagePath, function() { + var newFileEntry = new window.FileEntry(path.fileName, path.fullPath, new window.FileSystem(path.fsName, fileSystem.root)); + + newFileEntry.file_ = new MyFile({ + size: 0, + name: newFileEntry.name, + lastModifiedDate: new Date(), + storagePath: path.storagePath + }); + + indexedDB.put(newFileEntry, path.storagePath, successCallback, errorCallback); + }, errorCallback); + } else { + if (errorCallback) { + errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + } + } + } else if ((!options.create || options.create === false) && !fileEntry) { + // If create is not true and the path doesn't exist, getFile must fail. + if (errorCallback) { + errorCallback(window.FileError.NOT_FOUND_ERR); + } + } else if ((!options.create || options.create === false) && fileEntry && + fileEntry.isDirectory) { + // If create is not true and the path exists, but is a directory, getFile + // must fail. + if (errorCallback) { + errorCallback(window.FileError.TYPE_MISMATCH_ERR); + } + } else { + // Otherwise, if no other error occurs, getFile must return a FileEntry + // corresponding to path. + + successCallback(fileEntryFromIdbEntry(fileEntry)); + } + }, errorCallback); +} + +function getFileHandler(successCallback, errorCallback, module, event, args) { + getFile(successCallback, errorCallback, args); +} + +function getFileMetadata(successCallback, errorCallback, module, event, args) { + var fullPath = args[0]; + + getFile(function(fileEntry) { + successCallback(new window.File(fileEntry.file_.name, fileEntry.fullPath, '', fileEntry.file_.lastModifiedDate, + fileEntry.file_.size)); + }, errorCallback, [fullPath, null]); +} + +function setMetadata(successCallback, errorCallback, module, event, args) { + var fullPath = args[0]; + var metadataObject = args[1]; + + getFile(function (fileEntry) { + fileEntry.file_.lastModifiedDate = metadataObject.modificationTime; + indexedDB.put(fileEntry, fileEntry.file_.storagePath, successCallback, errorCallback); + }, errorCallback, [fullPath, null]); +} + +function write(successCallback, errorCallback, args) { + var fileName = args[0], + data = args[1], + position = args[2], + isBinary = args[3]; // jshint ignore: line + + if (!data) { + errorCallback && errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + return; + } + + if (typeof data === 'string' || data instanceof String) { + data = new Blob([data]); + } + + getFile(function(fileEntry) { + var blob_ = fileEntry.file_.blob_; + + if (!blob_) { + blob_ = new Blob([data], {type: data.type}); + } else { + // Calc the head and tail fragments + var head = blob_.slice(0, position); + var tail = blob_.slice(position + (data.size || data.byteLength)); + + // Calc the padding + var padding = position - head.size; + if (padding < 0) { + padding = 0; + } + + // Do the 'write'. In fact, a full overwrite of the Blob. + blob_ = new Blob([head, new Uint8Array(padding), data, tail], + {type: data.type}); + } + + // Set the blob we're writing on this file entry so we can recall it later. + fileEntry.file_.blob_ = blob_; + fileEntry.file_.lastModifiedDate = new Date() || null; + fileEntry.file_.size = blob_.size; + fileEntry.file_.name = blob_.name; + fileEntry.file_.type = blob_.type; + + indexedDB.put(fileEntry, fileEntry.file_.storagePath, function() { + successCallback(data.size || data.byteLength); + }, errorCallback); + }, errorCallback, [fileName, null]); +} + +function writeHandler(successCallback, errorCallback, module, event, args) { + write(successCallback, errorCallback, args); +} + +function readAsTextHandler(successCallback, errorCallback, module, event, args) { + var fileName = args[0], + enc = args[1], + startPos = args[2], + endPos = args[3]; + + readAs('text', fileName, enc, startPos, endPos, successCallback, errorCallback); +} + +function readAsDataURLHandler(successCallback, errorCallback, module, event, args) { + var fileName = args[0], + startPos = args[1], + endPos = args[2]; + + readAs('dataURL', fileName, null, startPos, endPos, successCallback, errorCallback); +} + +function readAsBinaryStringHandler(successCallback, errorCallback, module, event, args) { + var fileName = args[0], + startPos = args[1], + endPos = args[2]; + + readAs('binaryString', fileName, null, startPos, endPos, successCallback, errorCallback); +} + +function readAsArrayBufferHandler(successCallback, errorCallback, module, event, args) { + var fileName = args[0], + startPos = args[1], + endPos = args[2]; + + readAs('arrayBuffer', fileName, null, startPos, endPos, successCallback, errorCallback); +} + +function removeRecursively(successCallback, errorCallback, module, event, args) { + removeHandler(successCallback, errorCallback, module, event, args); +} + +function remove(successCallback, errorCallback, args) { + var fullPath = resolveToFullPath_(args[0]).storagePath; + if (fullPath === pathsPrefix.cacheDirectory || fullPath === pathsPrefix.dataDirectory) { + errorCallback(window.FileError.NO_MODIFICATION_ALLOWED_ERR); + return; + } + + function deleteEntry(isDirectory) { + // TODO: This doesn't protect against directories that have content in it. + // Should throw an error instead if the dirEntry is not empty. + indexedDB['delete'](fullPath, function() { + successCallback && successCallback(); + }, function() { + errorCallback && errorCallback(); + }, isDirectory); + } + + // We need to to understand what we are deleting: + getDirectory(function(entry) { + deleteEntry(entry.isDirectory); + }, function(){ + //DirectoryEntry was already deleted or entry is FileEntry + deleteEntry(false); + }, [fullPath, null, {create: false}]); +} + +function removeHandler(successCallback, errorCallback, module, event, args) { + remove(successCallback, errorCallback, args); +} + +function getDirectory(successCallback, errorCallback, args) { + var fullPath = args[0]; + var path = args[1]; + var options = args[2]; + + // Create an absolute path if we were handed a relative one. + path = resolveToFullPath_(fullPath, path); + + indexedDB.get(path.storagePath, function(folderEntry) { + if (!options) { + options = {}; + } + + if (options.create === true && options.exclusive === true && folderEntry) { + // If create and exclusive are both true, and the path already exists, + // getDirectory must fail. + if (errorCallback) { + errorCallback(window.FileError.PATH_EXISTS_ERR); + } + // There is a strange bug in mobilespec + FF, which results in coming to multiple else-if's + // so we are shielding from it with returns. + return; + } + + if (options.create === true && !folderEntry) { + // If create is true, the path doesn't exist, and no other error occurs, + // getDirectory must create it as a zero-length file and return a corresponding + // MyDirectoryEntry. + var dirEntry = new window.DirectoryEntry(path.fileName, path.fullPath, new window.FileSystem(path.fsName, fileSystem.root)); + + indexedDB.put(dirEntry, path.storagePath, successCallback, errorCallback); + return; + } + + if (options.create === true && folderEntry) { + + if (folderEntry.isDirectory) { + // IDB won't save methods, so we need re-create the MyDirectoryEntry. + successCallback(new window.DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem)); + } else { + if (errorCallback) { + errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + } + } + return; + } + + if ((!options.create || options.create === false) && !folderEntry) { + // Handle root special. It should always exist. + if (path.fullPath === DIR_SEPARATOR) { + successCallback(fileSystem.root); + return; + } + + // If create is not true and the path doesn't exist, getDirectory must fail. + if (errorCallback) { + errorCallback(window.FileError.NOT_FOUND_ERR); + } + + return; + } + if ((!options.create || options.create === false) && folderEntry && folderEntry.isFile) { + // If create is not true and the path exists, but is a file, getDirectory + // must fail. + if (errorCallback) { + errorCallback(window.FileError.TYPE_MISMATCH_ERR); + } + return; + } + + // Otherwise, if no other error occurs, getDirectory must return a + // MyDirectoryEntry corresponding to path. + + // IDB won't' save methods, so we need re-create MyDirectoryEntry. + successCallback(new window.DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem)); + }, errorCallback); +} + +function getDirectoryHandler(successCallback, errorCallback, module, event, args) { + getDirectory(successCallback, errorCallback, args); +} + +function getParentHandler(successCallback, errorCallback, module, args) { + if (typeof successCallback !== 'function') { + throw Error('Expected successCallback argument.'); + } + + var fullPath = args[0]; + //fullPath is like this: + //file:///persistent/path/to/file or + //file:///persistent/path/to/directory/ + + if (fullPath === DIR_SEPARATOR || fullPath === pathsPrefix.cacheDirectory || + fullPath === pathsPrefix.dataDirectory) { + successCallback(fileSystem.root); + return; + } + + //To delete all slashes at the end + while (fullPath[fullPath.length - 1] === '/') { + fullPath = fullPath.substr(0, fullPath.length - 1); + } + + var pathArr = fullPath.split(DIR_SEPARATOR); + pathArr.pop(); + var parentName = pathArr.pop(); + var path = pathArr.join(DIR_SEPARATOR) + DIR_SEPARATOR; + + //To get parent of root files + var joined = path + parentName + DIR_SEPARATOR;//is like this: file:///persistent/ + if (joined === pathsPrefix.cacheDirectory || joined === pathsPrefix.dataDirectory) { + getDirectory(successCallback, errorCallback, [joined, DIR_SEPARATOR, {create: false}]); + return; + } + + getDirectory(successCallback, errorCallback, [path, parentName, {create: false}]); +} + +function copyTo(successCallback, errorCallback, args) { + var srcPath = args[0]; + var parentFullPath = args[1]; + var name = args[2]; + + if (name.indexOf('/') !== -1 || srcPath === parentFullPath + name) { + if (errorCallback) { + errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + } + + return; + } + + // Read src file + getFile(function(srcFileEntry) { + + var path = resolveToFullPath_(parentFullPath); + //Check directory + getDirectory(function() { + + // Create dest file + getFile(function(dstFileEntry) { + + write(function() { + successCallback(dstFileEntry); + }, errorCallback, [dstFileEntry.file_.storagePath, srcFileEntry.file_.blob_, 0]); + + }, errorCallback, [parentFullPath, name, {create: true}]); + + }, function() { if (errorCallback) { errorCallback(window.FileError.NOT_FOUND_ERR); }}, + [path.storagePath, null, {create:false}]); + + }, errorCallback, [srcPath, null]); +} + +function copyToHandler(successCallback, errorCallback, module, event, args) { + copyTo(successCallback, errorCallback, args); +} + +function moveToHandler(successCallback, errorCallback, module, event, args) { + var srcPath = args[0]; + // parentFullPath and name parameters is ignored because + // args is being passed downstream to exports.copyTo method + var parentFullPath = args[1]; // jshint ignore: line + var name = args[2]; // jshint ignore: line + + copyTo(function (fileEntry) { + remove(function () { + successCallback(fileEntry); + }, errorCallback, [srcPath]); + }, errorCallback, args); +} + +function resolveLocalFileSystemURI(successCallback, errorCallback, args) { + var path = args[0]; + + // Ignore parameters + if (path.indexOf('?') !== -1) { + path = String(path).split('?')[0]; + } + + // support for encodeURI + if (/\%5/g.test(path) || /\%20/g.test(path)) { + path = decodeURI(path); + } + + if (path.trim()[0] === '/') { + errorCallback && errorCallback(window.FileError.ENCODING_ERR); + return; + } + + //support for cdvfile + if (path.trim().substr(0,7) === 'cdvfile') { + if (path.indexOf('cdvfile://localhost') === -1) { + errorCallback && errorCallback(window.FileError.ENCODING_ERR); + return; + } + + var indexPersistent = path.indexOf('persistent'); + var indexTemporary = path.indexOf('temporary'); + + //cdvfile://localhost/persistent/path/to/file + if (indexPersistent !== -1) { + path = 'file:///persistent' + path.substr(indexPersistent + 10); + } else if (indexTemporary !== -1) { + path = 'file:///temporary' + path.substr(indexTemporary + 9); + } else { + errorCallback && errorCallback(window.FileError.ENCODING_ERR); + return; + } + } + + // to avoid path form of '///path/to/file' + function handlePathSlashes(path) { + var cutIndex = 0; + for (var i = 0; i < path.length - 1; i++) { + if (path[i] === DIR_SEPARATOR && path[i + 1] === DIR_SEPARATOR) { + cutIndex = i + 1; + } else break; + } + + return path.substr(cutIndex); + } + + // Handle localhost containing paths (see specs ) + if (path.indexOf('file://localhost/') === 0) { + path = path.replace('file://localhost/', 'file:///'); + } + + if (path.indexOf(pathsPrefix.dataDirectory) === 0) { + path = path.substring(pathsPrefix.dataDirectory.length - 1); + path = handlePathSlashes(path); + + requestFileSystem(function() { + getFile(successCallback, function() { + getDirectory(successCallback, errorCallback, [pathsPrefix.dataDirectory, path, + {create: false}]); + }, [pathsPrefix.dataDirectory, path, {create: false}]); + }, errorCallback, [window.LocalFileSystem.PERSISTENT]); + } else if (path.indexOf(pathsPrefix.cacheDirectory) === 0) { + path = path.substring(pathsPrefix.cacheDirectory.length - 1); + path = handlePathSlashes(path); + + requestFileSystem(function() { + getFile(successCallback, function() { + getDirectory(successCallback, errorCallback, [pathsPrefix.cacheDirectory, path, + {create: false}]); + }, [pathsPrefix.cacheDirectory, path, {create: false}]); + }, errorCallback, [window.LocalFileSystem.TEMPORARY]); + } else if (path.indexOf(pathsPrefix.applicationDirectory) === 0) { + path = path.substring(pathsPrefix.applicationDirectory.length); + //TODO: need to cut out redundant slashes? + + var xhr = new XMLHttpRequest(); + xhr.open('GET', path, true); + xhr.onreadystatechange = function () { + if (xhr.status === 200 && xhr.readyState === 4) { + requestFileSystem(function(fs) { + fs.name = location.hostname; + + //TODO: need to call exports.getFile(...) to handle errors correct + fs.root.getFile(path, {create: true}, writeFile, errorCallback); + }, errorCallback, [window.LocalFileSystem.PERSISTENT]); + } + }; + + xhr.onerror = function () { + errorCallback && errorCallback(window.FileError.NOT_READABLE_ERR); + }; + + xhr.send(); + } else { + errorCallback && errorCallback(window.FileError.NOT_FOUND_ERR); + } + + function writeFile(entry) { + entry.createWriter(function (fileWriter) { + fileWriter.onwriteend = function (evt) { + if (!evt.target.error) { + entry.filesystemName = location.hostname; + successCallback(entry); + } + }; + fileWriter.onerror = function () { + errorCallback && errorCallback(window.FileError.NOT_READABLE_ERR); + }; + fileWriter.write(new Blob([xhr.response])); + }, errorCallback); + } +} + +function resolveLocalFileSystemURIHandler(successCallback, errorCallback, module, event, args) { + resolveLocalFileSystemURI(successCallback, errorCallback, args); +} + +function requestAllPathsHandler(successCallback, errorCallback, module, event, args) { + successCallback(pathsPrefix); +} + +// This handler is required for tests and backwards compatibility +function _getLocalFilesystemPathHandler(successCallback, errorCallback, module, event, args) { + var url = args[0]; + var stringToCut = 'file://'; + var fileIndex = url.indexOf(stringToCut); + if (fileIndex !== -1) { + url = url.substr(stringToCut.length, url.length-stringToCut.length); + } + successCallback(url); +} + +function notifyNotSupported(success, fail, args) { + fail('This method is not supported yet'); +} + +module.exports = { + 'File': { + 'requestAllPaths': requestAllPathsHandler, + 'getDirectory': getDirectoryHandler, + 'removeRecursively': removeRecursively, + 'getFile': getFileHandler, + 'readEntries': readEntriesHandler, + 'getFileMetadata': getFileMetadata, + 'setMetadata': setMetadata, + 'moveTo': moveToHandler, + 'copyTo': copyToHandler, + 'remove': removeHandler, + 'getParent': getParentHandler, + 'readAsDataURL': readAsDataURLHandler, + 'readAsBinaryString': readAsBinaryStringHandler, + 'readAsArrayBuffer': readAsArrayBufferHandler, + 'readAsText': readAsTextHandler, + 'write': writeHandler, + 'requestFileSystem': requestFileSystemHandler, + 'resolveLocalFileSystemURI': resolveLocalFileSystemURIHandler, + // exec's below are not implemented in browser platform + 'truncate': notifyNotSupported, + 'requestAllFileSystems': notifyNotSupported, + // method below is used for backward compatibility w/ old File plugin implementation + '_getLocalFilesystemPath': _getLocalFilesystemPathHandler + } +}; diff --git a/src/plugins/cordova-plugin-file/app-host-webkit-handlers.js b/src/plugins/cordova-plugin-file/app-host-webkit-handlers.js new file mode 100644 index 00000000..30aa5e67 --- /dev/null +++ b/src/plugins/cordova-plugin-file/app-host-webkit-handlers.js @@ -0,0 +1,201 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +var filePluginIsReadyEvent = new Event('filePluginIsReady'); +var PERSISTENT_FS_QUOTA = 5 * 1024 * 1024; + +var entryFunctionsCreated = false; +var quotaWasRequested = false; +var eventWasThrown = false; + +window.initPersistentFileSystem = function(size, win, fail) { + if (navigator.webkitPersistentStorage) { + navigator.webkitPersistentStorage.requestQuota(size, win, fail); + return; + } + + fail('This browser does not support this function'); +}; + +window.isFilePluginReadyRaised = function () { return eventWasThrown; }; + +window.initPersistentFileSystem(PERSISTENT_FS_QUOTA, function() { + console.log('Persistent fs quota granted'); + quotaWasRequested = true; +}, function(e){ + console.log('Error occured while trying to request Persistent fs quota: ' + JSON.stringify(e)); +}); + +function dispatchEventIfReady() { + if (entryFunctionsCreated && quotaWasRequested) { + window.dispatchEvent(filePluginIsReadyEvent); + eventWasThrown = true; + } else { + setTimeout(dispatchEventIfReady, 100); + } +} + +// We create and fire event 'filePluginIsReady' when file system persistent file quota +// is granted and entry functions are overriden, so we can already work with file system properly. +dispatchEventIfReady(); + +// We must override some functionality so that plugin can work properly, +// for example, if we override window.requestFileSystem or window.resolveLocalFileSystemURL, +// they might be overrided later, and if we will wait for deviceready event, we assume that +// these functions will not be overrided later. +document.addEventListener('deviceready', function () { + window.requestFileSystem = window.webkitRequestFileSystem; + + if (!window.requestFileSystem) { + window.requestFileSystem = function(type, size, win, fail) { + if (fail) { + fail('Not supported'); + } + }; + } else { + window.requestFileSystem(window.TEMPORARY, 1, createFileEntryFunctions, function() {}); + } + + function createFileEntryFunctions(fs) { + fs.root.getFile('todelete_658674_833_4_cdv', {create: true}, function(fileEntry) { + var fileEntryType = Object.getPrototypeOf(fileEntry); + var entryType = Object.getPrototypeOf(fileEntryType); + + // Save the original method + var origToURL = entryType.toURL; + entryType.toURL = function () { + var origURL = origToURL.call(this); + if (this.isDirectory && origURL.substr(-1) !== '/') { + return origURL + '/'; + } + return origURL; + }; + + entryType.toNativeURL = function () { + console.warn('DEPRECATED: Update your code to use \'toURL\''); + return this.toURL(); + }; + + entryType.toInternalURL = function() { + if (this.toURL().indexOf('persistent') > -1) { + return 'cdvfile://localhost/persistent' + this.fullPath; + } + + if (this.toURL().indexOf('temporary') > -1) { + return 'cdvfile://localhost/temporary' + this.fullPath; + } + }; + + entryType.setMetadata = function(win, fail /*, metadata*/) { + fail && fail('Not supported'); + }; + + fileEntry.createWriter(function(writer) { + var originalWrite = writer.write; + var writerProto = Object.getPrototypeOf(writer); + writerProto.write = function(blob) { + if(blob instanceof Blob) { + originalWrite.apply(this, [blob]); + } else { + var realBlob = new Blob([blob]); + originalWrite.apply(this, [realBlob]); + } + }; + + fileEntry.remove(function(){ entryFunctionsCreated = true; }, function(){ /* empty callback */ }); + }); + }); + } + + if (!window.resolveLocalFileSystemURL) { + window.resolveLocalFileSystemURL = function(url, win, fail) { + if(fail) { + fail('Not supported'); + } + }; + } + + // Resolves a filesystem entry by its path - which is passed either in standard (filesystem:file://) or + // Cordova-specific (cdvfile://) universal way. + // Aligns with specification: http://www.w3.org/TR/2011/WD-file-system-api-20110419/#widl-LocalFileSystem-resolveLocalFileSystemURL + var nativeResolveLocalFileSystemURL = window.webkitResolveLocalFileSystemURL || window.resolveLocalFileSystemURL; + window.resolveLocalFileSystemURL = function(url, win, fail) { + /* If url starts with `cdvfile` then we need convert it to Chrome real url first: + cdvfile://localhost/persistent/path/to/file -> filesystem:file://persistent/path/to/file */ + if (url.trim().substr(0,7) === 'cdvfile') { + /* Quirk: + Plugin supports cdvfile://localhost (local resources) only. + I.e. external resources are not supported via cdvfile. */ + if (url.indexOf('cdvfile://localhost') !== -1) { + // Browser supports temporary and persistent only + var indexPersistent = url.indexOf('persistent'); + var indexTemporary = url.indexOf('temporary'); + + /* Chrome urls start with 'filesystem:' prefix. See quirk: + toURL function in Chrome returns filesystem:-prefixed path depending on application host. + For example, filesystem:file:///persistent/somefile.txt, + filesystem:http://localhost:8080/persistent/somefile.txt. */ + var prefix = 'filesystem:file:///'; + if (location.protocol !== 'file:') { + prefix = 'filesystem:' + location.origin + '/'; + } + + var result; + if (indexPersistent !== -1) { + // cdvfile://localhost/persistent/path/to/file -> filesystem:file://persistent/path/to/file + // or filesystem:http://localhost:8080/persistent/path/to/file + result = prefix + 'persistent' + url.substr(indexPersistent + 10); + nativeResolveLocalFileSystemURL(result, win, fail); + return; + } + + if (indexTemporary !== -1) { + // cdvfile://localhost/temporary/path/to/file -> filesystem:file://temporary/path/to/file + // or filesystem:http://localhost:8080/temporary/path/to/file + result = prefix + 'temporary' + url.substr(indexTemporary + 9); + nativeResolveLocalFileSystemURL(result, win, fail); + return; + } + } + + // cdvfile other than local file resource is not supported + fail && fail(function () {throw new window.FileError(window.FileError.ENCODING_ERR);}); + } else if (url.trim().indexOf('file://') === 0) { + // ADDED + url = 'filesystem:http://' + url.replace('file://', ''); + nativeResolveLocalFileSystemURL(url, win, fail); + } else { + nativeResolveLocalFileSystemURL(url, win, fail); + } + }; +}, false); + +// This handler is required for tests and backwards compatibility +function _getLocalFilesystemPathHandler(successCallback, errorCallback, module, event, args) { + var url = args[0]; + var localhostIndex = url.indexOf('localhost'); + if (localhostIndex !== -1) { + url = url.substr(localhostIndex, url.length-localhostIndex); + } + successCallback(url); +} + +function requestAllPathsHandler(successCallback, errorCallback, module, event, args) { + var pathsPrefix = { + // Read-only directory where the application is installed. + applicationDirectory: location.origin + '/', + // Where to put app-specific data files. + dataDirectory: 'filesystem:file:///persistent/', + // Cached files that should survive app restarts. + // Apps should not rely on the OS to delete files in here. + cacheDirectory: 'filesystem:file:///temporary/', + }; + + successCallback(pathsPrefix); +} + +module.exports = { + 'File': { + '_getLocalFilesystemPath': _getLocalFilesystemPathHandler, + 'requestAllPaths': requestAllPathsHandler + } +}; diff --git a/src/plugins/cordova-plugin-file/indexedDB.js b/src/plugins/cordova-plugin-file/indexedDB.js new file mode 100644 index 00000000..108d87ea --- /dev/null +++ b/src/plugins/cordova-plugin-file/indexedDB.js @@ -0,0 +1,191 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +var indexedDB = { + db: null +}; + +var FILE_STORE_ = 'entries', + DIR_SEPARATOR = '/', + unicodeLastChar = 65535; + +indexedDB.open = function(dbName, successCallback, errorCallback) { + var self = this; + + // TODO: FF 12.0a1 isn't liking a db name with : in it. + var request = window.indexedDB.open(dbName.replace(':', '_')/*, 1 /*version*/); + + request.onerror = errorCallback || onError; + + request.onupgradeneeded = function(e) { + // First open was called or higher db version was used. + + // console.log('onupgradeneeded: oldVersion:' + e.oldVersion, + // 'newVersion:' + e.newVersion); + + self.db = e.target.result; + self.db.onerror = onError; + + if (!self.db.objectStoreNames.contains(FILE_STORE_)) { + self.db.createObjectStore(FILE_STORE_/*,{keyPath: 'id', autoIncrement: true}*/); + } + }; + + request.onsuccess = function(e) { + self.db = e.target.result; + self.db.onerror = onError; + successCallback(e); + }; + + request.onblocked = errorCallback || onError; +}; + +indexedDB.close = function() { + this.db.close(); + this.db = null; +}; + +indexedDB.get = function(fullPath, successCallback, errorCallback) { + if (!this.db) { + errorCallback && errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + return; + } + + var tx = this.db.transaction([FILE_STORE_], 'readonly'); + + var request = tx.objectStore(FILE_STORE_).get(fullPath); + + tx.onabort = errorCallback || onError; + tx.oncomplete = function() { + successCallback(request.result); + }; +}; + +indexedDB.getAllEntries = function(fullPath, storagePath, successCallback, errorCallback) { + if (!this.db) { + errorCallback && errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + return; + } + + var results = []; + + if (storagePath[storagePath.length - 1] === DIR_SEPARATOR) { + storagePath = storagePath.substring(0, storagePath.length - 1); + } + + var range = window.IDBKeyRange.bound(storagePath + DIR_SEPARATOR + ' ', + storagePath + DIR_SEPARATOR + String.fromCharCode(unicodeLastChar)); + + var tx = this.db.transaction([FILE_STORE_], 'readonly'); + tx.onabort = errorCallback || onError; + tx.oncomplete = function() { + results = results.filter(function(val) { + var pathWithoutSlash = val.fullPath; + + if (val.fullPath[val.fullPath.length - 1] === DIR_SEPARATOR) { + pathWithoutSlash = pathWithoutSlash.substr(0, pathWithoutSlash.length - 1); + } + + var valPartsLen = pathWithoutSlash.split(DIR_SEPARATOR).length; + var fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length; + + /* Input fullPath parameter equals '//' for root folder */ + /* Entries in root folder has valPartsLen equals 2 (see below) */ + if (fullPath[fullPath.length -1] === DIR_SEPARATOR && fullPath.trim().length === 2) { + fullPathPartsLen = 1; + } else if (fullPath[fullPath.length -1] === DIR_SEPARATOR) { + fullPathPartsLen = fullPath.substr(0, fullPath.length - 1).split(DIR_SEPARATOR).length; + } else { + fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length; + } + + if (valPartsLen === fullPathPartsLen + 1) { + // If this a subfolder and entry is a direct child, include it in + // the results. Otherwise, it's not an entry of this folder. + return val; + } else return false; + }); + + successCallback(results); + }; + + var request = tx.objectStore(FILE_STORE_).openCursor(range); + + request.onsuccess = function(e) { + var cursor = e.target.result; + if (cursor) { + var val = cursor.value; + + results.push(val.isFile ? fileEntryFromIdbEntry(val) : new window.DirectoryEntry(val.name, val.fullPath, val.filesystem)); + cursor['continue'](); + } + }; +}; + +indexedDB['delete'] = function(fullPath, successCallback, errorCallback, isDirectory) { + if (!indexedDB.db) { + errorCallback && errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + return; + } + + var tx = this.db.transaction([FILE_STORE_], 'readwrite'); + tx.oncomplete = successCallback; + tx.onabort = errorCallback || onError; + tx.oncomplete = function() { + if (isDirectory) { + //We delete nested files and folders after deleting parent folder + //We use ranges: https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange + fullPath = fullPath + DIR_SEPARATOR; + + //Range contains all entries in the form fullPath where + //symbol in the range from ' ' to symbol which has code `unicodeLastChar` + var range = window.IDBKeyRange.bound(fullPath + ' ', fullPath + String.fromCharCode(unicodeLastChar)); + + var newTx = this.db.transaction([FILE_STORE_], 'readwrite'); + newTx.oncomplete = successCallback; + newTx.onabort = errorCallback || onError; + newTx.objectStore(FILE_STORE_)['delete'](range); + } else { + successCallback(); + } + }; + tx.objectStore(FILE_STORE_)['delete'](fullPath); +}; + +indexedDB.put = function(entry, storagePath, successCallback, errorCallback) { + if (!this.db) { + errorCallback && errorCallback(window.FileError.INVALID_MODIFICATION_ERR); + return; + } + + var tx = this.db.transaction([FILE_STORE_], 'readwrite'); + tx.onabort = onError; + tx.oncomplete = function() { + // TODO: Error is thrown if we pass the request event back instead. + successCallback(entry); + }; + + tx.objectStore(FILE_STORE_).put(entry, storagePath); +}; + +function onError(e) { + switch (e.target.errorCode) { + case 12: + console.log('Error - Attempt to open db with a lower version than the ' + + 'current one.'); + break; + default: + console.log('errorCode: ' + e.target.errorCode); + } + + console.log(e, e.code, e.message); +} + +function fileEntryFromIdbEntry(fileEntry) { + // IDB won't save methods, so we need re-create the FileEntry. + var clonedFileEntry = new window.FileEntry(fileEntry.name, fileEntry.fullPath, fileEntry.filesystem); + clonedFileEntry.file_ = fileEntry.file_; + + return clonedFileEntry; +} + +module.exports = indexedDB; diff --git a/src/plugins/cordova-plugin-geolocation/Coordinates.js b/src/plugins/cordova-plugin-geolocation/Coordinates.js new file mode 100644 index 00000000..b7e3210b --- /dev/null +++ b/src/plugins/cordova-plugin-geolocation/Coordinates.js @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Based on Apache Cordova geolocation plugin's Coordinates implementation. +// See https://github.com/apache/cordova-plugin-geolocation/blob/master/www/Coordinates.js + +/** + * This class contains position information. + * @param {Object} lat + * @param {Object} lng + * @param {Object} alt + * @param {Object} acc + * @param {Object} head + * @param {Object} vel + * @param {Object} altacc + * @constructor + */ +var Coordinates = function(lat, lng, alt, acc, head, vel, altacc) { + /** + * The latitude of the position. + */ + this.latitude = lat; + /** + * The longitude of the position, + */ + this.longitude = lng; + /** + * The accuracy of the position. + */ + this.accuracy = acc; + /** + * The altitude of the position. + */ + this.altitude = (alt !== undefined ? alt : null); + /** + * The direction the device is moving at the position. + */ + this.heading = (head !== undefined ? head : null); + /** + * The velocity with which the device is moving at the position. + */ + this.speed = (vel !== undefined ? vel : null); + + if (this.speed === 0 || this.speed === null) { + this.heading = NaN; + } + + /** + * The altitude accuracy of the position. + */ + this.altitudeAccuracy = (altacc !== undefined) ? altacc : null; +}; + +module.exports = Coordinates; diff --git a/src/plugins/cordova-plugin-geolocation/OpenLayers.js b/src/plugins/cordova-plugin-geolocation/OpenLayers.js new file mode 100644 index 00000000..8fd3c4e5 --- /dev/null +++ b/src/plugins/cordova-plugin-geolocation/OpenLayers.js @@ -0,0 +1,1443 @@ +/* + + OpenLayers.js -- OpenLayers Map Viewer Library + + Copyright (c) 2006-2013 by OpenLayers Contributors + Published under the 2-clause BSD license. + See http://openlayers.org/dev/license.txt for the full text of the license, and http://openlayers.org/dev/authors.txt for full list of contributors. + + Includes compressed code under the following licenses: + + (For uncompressed versions of the code used, please see the + OpenLayers Github repository: ) + + */ + +/** + * Contains XMLHttpRequest.js + * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + */ + +/** + * OpenLayers.Util.pagePosition is based on Yahoo's getXY method, which is + * Copyright (c) 2006, Yahoo! Inc. + * All rights reserved. + * + * Redistribution and use of this software in source and binary forms, with or + * without modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * 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. + * + * * Neither the name of Yahoo! Inc. nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission of Yahoo! Inc. + * + * 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 OWNER 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. + */ +var OpenLayers={VERSION_NUMBER:"Release 2.13.1",singleFile:!0,_getScriptLocation:function(){for(var a=/(^|(.*?\/))(OpenLayers[^\/]*?\.js)(\?|$)/,b=document.getElementsByTagName("script"),c,d="",e=0,f=b.length;ethis.right)this.right=a.right;if(null==this.top||a.top>this.top)this.top=a.top}},extendXY:function(a,b){this.centerLonLat=null;if(null==this.left||athis.right)this.right=a;if(null==this.top||b>this.top)this.top=b},containsLonLat:function(a,b){"boolean"===typeof b&&(b={inclusive:b});b=b||{};var c=this.contains(a.lon,a.lat,b.inclusive),d=b.worldBounds;d&&!c&&(c=d.getWidth(), + d=Math.round((a.lon-(d.left+d.right)/2)/c),c=this.containsLonLat({lon:a.lon-d*c,lat:a.lat},{inclusive:b.inclusive}));return c},containsPixel:function(a,b){return this.contains(a.x,a.y,b)},contains:function(a,b,c){null==c&&(c=!0);if(null==a||null==b)return!1;a=OpenLayers.Util.toFloat(a);b=OpenLayers.Util.toFloat(b);var d=!1;return d=c?a>=this.left&&a<=this.right&&b>=this.bottom&&b<=this.top:a>this.left&&athis.bottom&&b=c.bottom&&a.top<=c.top||c.top>a.bottom&&c.top=c.left&&a.left<=c.right||c.left>=a.left&&c.left<=a.right,f=a.right>=c.left&&a.right<=c.right||c.right>=a.left&&c.right<=a.right,d=(a.bottom>=c.bottom&&a.bottom<=c.top||c.bottom>= + a.bottom&&c.bottom<=a.top||d)&&(e||f);if(b.worldBounds&&!d){var g=b.worldBounds,e=g.getWidth(),f=!g.containsBounds(c),g=!g.containsBounds(a);f&&!g?(a=a.add(-e,0),d=c.intersectsBounds(a,{inclusive:b.inclusive})):g&&!f&&(c=c.add(-e,0),d=a.intersectsBounds(c,{inclusive:b.inclusive}))}return d},containsBounds:function(a,b,c){null==b&&(b=!1);null==c&&(c=!0);var d=this.contains(a.left,a.bottom,c),e=this.contains(a.right,a.bottom,c),f=this.contains(a.left,a.top,c);a=this.contains(a.right,a.top,c);return b? + d||e||f||a:d&&e&&f&&a},determineQuadrant:function(a){var b="",c=this.getCenterLonLat(),b=b+(a.lat=a.right&&e.right>a.right;)e=e.add(-f,0);c=e.left+c;ca.left&&e.right-d>a.right)&&(e=e.add(-f,0))}return e},CLASS_NAME:"OpenLayers.Bounds"}); +OpenLayers.Bounds.fromString=function(a,b){var c=a.split(",");return OpenLayers.Bounds.fromArray(c,b)};OpenLayers.Bounds.fromArray=function(a,b){return!0===b?new OpenLayers.Bounds(a[1],a[0],a[3],a[2]):new OpenLayers.Bounds(a[0],a[1],a[2],a[3])};OpenLayers.Bounds.fromSize=function(a){return new OpenLayers.Bounds(0,a.h,a.w,0)};OpenLayers.Bounds.oppositeQuadrant=function(a){var b;b=""+("t"==a.charAt(0)?"b":"t");return b+="l"==a.charAt(1)?"r":"l"};OpenLayers.Element={visible:function(a){return"none"!=OpenLayers.Util.getElement(a).style.display},toggle:function(){for(var a=0,b=arguments.length;aa.right;)b.lon-=a.getWidth()}return b},CLASS_NAME:"OpenLayers.LonLat"}); +OpenLayers.LonLat.fromString=function(a){a=a.split(",");return new OpenLayers.LonLat(a[0],a[1])};OpenLayers.LonLat.fromArray=function(a){var b=OpenLayers.Util.isArray(a);return new OpenLayers.LonLat(b&&a[0],b&&a[1])};OpenLayers.Pixel=OpenLayers.Class({x:0,y:0,initialize:function(a,b){this.x=parseFloat(a);this.y=parseFloat(b)},toString:function(){return"x="+this.x+",y="+this.y},clone:function(){return new OpenLayers.Pixel(this.x,this.y)},equals:function(a){var b=!1;null!=a&&(b=this.x==a.x&&this.y==a.y||isNaN(this.x)&&isNaN(this.y)&&isNaN(a.x)&&isNaN(a.y));return b},distanceTo:function(a){return Math.sqrt(Math.pow(this.x-a.x,2)+Math.pow(this.y-a.y,2))},add:function(a,b){if(null==a||null==b)throw new TypeError("Pixel.add cannot receive null values"); + return new OpenLayers.Pixel(this.x+a,this.y+b)},offset:function(a){var b=this.clone();a&&(b=this.add(a.x,a.y));return b},CLASS_NAME:"OpenLayers.Pixel"});OpenLayers.Size=OpenLayers.Class({w:0,h:0,initialize:function(a,b){this.w=parseFloat(a);this.h=parseFloat(b)},toString:function(){return"w="+this.w+",h="+this.h},clone:function(){return new OpenLayers.Size(this.w,this.h)},equals:function(a){var b=!1;null!=a&&(b=this.w==a.w&&this.h==a.h||isNaN(this.w)&&isNaN(this.h)&&isNaN(a.w)&&isNaN(a.h));return b},CLASS_NAME:"OpenLayers.Size"});OpenLayers.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},userError:function(a){alert(a)},assert:function(){},dir:function(){},dirxml:function(){},trace:function(){},group:function(){},groupEnd:function(){},time:function(){},timeEnd:function(){},profile:function(){},profileEnd:function(){},count:function(){},CLASS_NAME:"OpenLayers.Console"}; +(function(){for(var a=document.getElementsByTagName("script"),b=0,c=a.length;bparseFloat(h)?(a.style.filter="alpha(opacity="+100*h+")",a.style.opacity=h):1==parseFloat(h)&&(a.style.filter="",a.style.opacity="")}; +OpenLayers.Util.createDiv=function(a,b,c,d,e,f,g,h){var k=document.createElement("div");d&&(k.style.backgroundImage="url("+d+")");a||(a=OpenLayers.Util.createUniqueID("OpenLayersDiv"));e||(e="absolute");OpenLayers.Util.modifyDOMElement(k,a,b,c,e,f,g,h);return k}; +OpenLayers.Util.createImage=function(a,b,c,d,e,f,g,h){var k=document.createElement("img");a||(a=OpenLayers.Util.createUniqueID("OpenLayersDiv"));e||(e="relative");OpenLayers.Util.modifyDOMElement(k,a,b,c,e,f,null,g);h&&(k.style.display="none",b=function(){k.style.display="";OpenLayers.Event.stopObservingElement(k)},OpenLayers.Event.observe(k,"load",b),OpenLayers.Event.observe(k,"error",b));k.style.alt=a;k.galleryImg="no";d&&(k.src=d);return k};OpenLayers.IMAGE_RELOAD_ATTEMPTS=0; +OpenLayers.Util.alphaHackNeeded=null;OpenLayers.Util.alphaHack=function(){if(null==OpenLayers.Util.alphaHackNeeded){var a=navigator.appVersion.split("MSIE"),a=parseFloat(a[1]),b=!1;try{b=!!document.body.filters}catch(c){}OpenLayers.Util.alphaHackNeeded=b&&5.5<=a&&7>a}return OpenLayers.Util.alphaHackNeeded}; +OpenLayers.Util.modifyAlphaImageDiv=function(a,b,c,d,e,f,g,h,k){OpenLayers.Util.modifyDOMElement(a,b,c,d,f,null,null,k);b=a.childNodes[0];e&&(b.src=e);OpenLayers.Util.modifyDOMElement(b,a.id+"_innerImage",null,d,"relative",g);OpenLayers.Util.alphaHack()&&("none"!=a.style.display&&(a.style.display="inline-block"),null==h&&(h="scale"),a.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+b.src+"', sizingMethod='"+h+"')",0<=parseFloat(a.style.opacity)&&1>parseFloat(a.style.opacity)&& +(a.style.filter+=" alpha(opacity="+100*a.style.opacity+")"),b.style.filter="alpha(opacity=0)")};OpenLayers.Util.createAlphaImageDiv=function(a,b,c,d,e,f,g,h,k){var l=OpenLayers.Util.createDiv();k=OpenLayers.Util.createImage(null,null,null,null,null,null,null,k);k.className="olAlphaImg";l.appendChild(k);OpenLayers.Util.modifyAlphaImageDiv(l,a,b,c,d,e,f,g,h);return l};OpenLayers.Util.upperCaseObject=function(a){var b={},c;for(c in a)b[c.toUpperCase()]=a[c];return b}; +OpenLayers.Util.applyDefaults=function(a,b){a=a||{};var c="function"==typeof window.Event&&b instanceof window.Event,d;for(d in b)if(void 0===a[d]||!c&&b.hasOwnProperty&&b.hasOwnProperty(d)&&!a.hasOwnProperty(d))a[d]=b[d];!c&&(b&&b.hasOwnProperty&&b.hasOwnProperty("toString")&&!a.hasOwnProperty("toString"))&&(a.toString=b.toString);return a}; +OpenLayers.Util.getParameterString=function(a){var b=[],c;for(c in a){var d=a[c];if(null!=d&&"function"!=typeof d){if("object"==typeof d&&d.constructor==Array){for(var e=[],f,g=0,h=d.length;ge&&(e="0"+e);e+="\u00b0";0<=c.indexOf("dm")&&(10>d&&(d="0"+d),e+=d+"'",0<=c.indexOf("dms")&&(10>f&&(f="0"+f),e+=f+'"'));return e="lon"==b?e+(0>a?OpenLayers.i18n("W"):OpenLayers.i18n("E")):e+(0>a?OpenLayers.i18n("S"):OpenLayers.i18n("N"))};OpenLayers.Format=OpenLayers.Class({options:null,externalProjection:null,internalProjection:null,data:null,keepData:!1,initialize:function(a){OpenLayers.Util.extend(this,a);this.options=a},destroy:function(){},read:function(a){throw Error("Read not implemented.");},write:function(a){throw Error("Write not implemented.");},CLASS_NAME:"OpenLayers.Format"});OpenLayers.Format.CSWGetRecords=function(a){a=OpenLayers.Util.applyDefaults(a,OpenLayers.Format.CSWGetRecords.DEFAULTS);var b=OpenLayers.Format.CSWGetRecords["v"+a.version.replace(/\./g,"_")];if(!b)throw"Unsupported CSWGetRecords version: "+a.version;return new b(a)};OpenLayers.Format.CSWGetRecords.DEFAULTS={version:"2.0.2"};OpenLayers.Control=OpenLayers.Class({id:null,map:null,div:null,type:null,allowSelection:!1,displayClass:"",title:"",autoActivate:!1,active:null,handlerOptions:null,handler:null,eventListeners:null,events:null,initialize:function(a){this.displayClass=this.CLASS_NAME.replace("OpenLayers.","ol").replace(/\./g,"");OpenLayers.Util.extend(this,a);this.events=new OpenLayers.Events(this);if(this.eventListeners instanceof Object)this.events.on(this.eventListeners);null==this.id&&(this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+ + "_"))},destroy:function(){this.events&&(this.eventListeners&&this.events.un(this.eventListeners),this.events.destroy(),this.events=null);this.eventListeners=null;this.handler&&(this.handler.destroy(),this.handler=null);if(this.handlers){for(var a in this.handlers)this.handlers.hasOwnProperty(a)&&"function"==typeof this.handlers[a].destroy&&this.handlers[a].destroy();this.handlers=null}this.map&&(this.map.removeControl(this),this.map=null);this.div=null},setMap:function(a){this.map=a;this.handler&& +this.handler.setMap(a)},draw:function(a){null==this.div&&(this.div=OpenLayers.Util.createDiv(this.id),this.div.className=this.displayClass,this.allowSelection||(this.div.className+=" olControlNoSelect",this.div.setAttribute("unselectable","on",0),this.div.onselectstart=OpenLayers.Function.False),""!=this.title&&(this.div.title=this.title));null!=a&&(this.position=a.clone());this.moveTo(this.position);return this.div},moveTo:function(a){null!=a&&null!=this.div&&(this.div.style.left=a.x+"px",this.div.style.top= + a.y+"px")},activate:function(){if(this.active)return!1;this.handler&&this.handler.activate();this.active=!0;this.map&&OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");this.events.triggerEvent("activate");return!0},deactivate:function(){return this.active?(this.handler&&this.handler.deactivate(),this.active=!1,this.map&&OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active"),this.events.triggerEvent("deactivate"), + !0):!1},CLASS_NAME:"OpenLayers.Control"});OpenLayers.Control.TYPE_BUTTON=1;OpenLayers.Control.TYPE_TOGGLE=2;OpenLayers.Control.TYPE_TOOL=3;OpenLayers.Event={observers:!1,KEY_SPACE:32,KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,element:function(a){return a.target||a.srcElement},isSingleTouch:function(a){return a.touches&&1==a.touches.length},isMultiTouch:function(a){return a.touches&&1Math.floor(a.pageY)||0===a.pageX&&Math.floor(d)>Math.floor(a.pageX))d-=c,e-=b;else if(ethis.duration&&this.stop()},CLASS_NAME:"OpenLayers.Tween"});OpenLayers.Easing={CLASS_NAME:"OpenLayers.Easing"};OpenLayers.Easing.Linear={easeIn:function(a,b,c,d){return c*a/d+b},easeOut:function(a,b,c,d){return c*a/d+b},easeInOut:function(a,b,c,d){return c*a/d+b},CLASS_NAME:"OpenLayers.Easing.Linear"}; +OpenLayers.Easing.Expo={easeIn:function(a,b,c,d){return 0==a?b:c*Math.pow(2,10*(a/d-1))+b},easeOut:function(a,b,c,d){return a==d?b+c:c*(-Math.pow(2,-10*a/d)+1)+b},easeInOut:function(a,b,c,d){return 0==a?b:a==d?b+c:1>(a/=d/2)?c/2*Math.pow(2,10*(a-1))+b:c/2*(-Math.pow(2,-10*--a)+2)+b},CLASS_NAME:"OpenLayers.Easing.Expo"}; +OpenLayers.Easing.Quad={easeIn:function(a,b,c,d){return c*(a/=d)*a+b},easeOut:function(a,b,c,d){return-c*(a/=d)*(a-2)+b},easeInOut:function(a,b,c,d){return 1>(a/=d/2)?c/2*a*a+b:-c/2*(--a*(a-2)-1)+b},CLASS_NAME:"OpenLayers.Easing.Quad"};OpenLayers.Projection=OpenLayers.Class({proj:null,projCode:null,titleRegEx:/\+title=[^\+]*/,initialize:function(a,b){OpenLayers.Util.extend(this,b);this.projCode=a;"object"==typeof Proj4js&&(this.proj=new Proj4js.Proj(a))},getCode:function(){return this.proj?this.proj.srsCode:this.projCode},getUnits:function(){return this.proj?this.proj.units:null},toString:function(){return this.getCode()},equals:function(a){var b=!1;a&&(a instanceof OpenLayers.Projection||(a=new OpenLayers.Projection(a)),"object"== +typeof Proj4js&&this.proj.defData&&a.proj.defData?b=this.proj.defData.replace(this.titleRegEx,"")==a.proj.defData.replace(this.titleRegEx,""):a.getCode&&(b=this.getCode(),a=a.getCode(),b=b==a||!!OpenLayers.Projection.transforms[b]&&OpenLayers.Projection.transforms[b][a]===OpenLayers.Projection.nullTransform));return b},destroy:function(){delete this.proj;delete this.projCode},CLASS_NAME:"OpenLayers.Projection"});OpenLayers.Projection.transforms={}; +OpenLayers.Projection.defaults={"EPSG:4326":{units:"degrees",maxExtent:[-180,-90,180,90],yx:!0},"CRS:84":{units:"degrees",maxExtent:[-180,-90,180,90]},"EPSG:900913":{units:"m",maxExtent:[-2.003750834E7,-2.003750834E7,2.003750834E7,2.003750834E7]}}; +OpenLayers.Projection.addTransform=function(a,b,c){if(c===OpenLayers.Projection.nullTransform){var d=OpenLayers.Projection.defaults[a];d&&!OpenLayers.Projection.defaults[b]&&(OpenLayers.Projection.defaults[b]=d)}OpenLayers.Projection.transforms[a]||(OpenLayers.Projection.transforms[a]={});OpenLayers.Projection.transforms[a][b]=c}; +OpenLayers.Projection.transform=function(a,b,c){if(b&&c)if(b instanceof OpenLayers.Projection||(b=new OpenLayers.Projection(b)),c instanceof OpenLayers.Projection||(c=new OpenLayers.Projection(c)),b.proj&&c.proj)a=Proj4js.transform(b.proj,c.proj,a);else{b=b.getCode();c=c.getCode();var d=OpenLayers.Projection.transforms;if(d[b]&&d[b][c])d[b][c](a)}return a};OpenLayers.Projection.nullTransform=function(a){return a}; +(function(){function a(a){a.x=180*a.x/d;a.y=180/Math.PI*(2*Math.atan(Math.exp(a.y/d*Math.PI))-Math.PI/2);return a}function b(a){a.x=a.x*d/180;var b=Math.log(Math.tan((90+a.y)*Math.PI/360))/Math.PI*d;a.y=Math.max(-2.003750834E7,Math.min(b,2.003750834E7));return a}function c(c,d){var e=OpenLayers.Projection.addTransform,f=OpenLayers.Projection.nullTransform,g,p,q,r,s;g=0;for(p=d.length;gb?b=0:b>this.layers.length&&(b=this.layers.length);if(c!=b){this.layers.splice(c,1);this.layers.splice(b,0,a);for(var c=0,d=this.layers.length;c=this.minPx.x+h?Math.round(a):0;b=f<=this.maxPx.y-k&&f>=this.minPx.y+k?Math.round(b):0;if(a||b){this.dragging||(this.dragging=!0,this.events.triggerEvent("movestart")); + this.center=null;a&&(this.layerContainerOriginPx.x-=a,this.minPx.x-=a,this.maxPx.x-=a);b&&(this.layerContainerOriginPx.y-=b,this.minPx.y-=b,this.maxPx.y-=b);this.applyTransform();d=0;for(e=this.layers.length;dc)if(this.fractionalZoom)a=this.getZoomForResolution(c);else for(var d=a|0,e=b.length;dthis.restrictedExtent.getWidth()?a=new OpenLayers.LonLat(g.lon,a.lat):f.leftthis.restrictedExtent.right&& + (a=a.add(this.restrictedExtent.right-f.right,0));f.getHeight()>this.restrictedExtent.getHeight()?a=new OpenLayers.LonLat(a.lon,g.lat):f.bottomthis.restrictedExtent.top&&(a=a.add(0,this.restrictedExtent.top-f.top))}}e=e||this.isValidZoomLevel(b)&&b!=this.getZoom();f=this.isValidLonLat(a)&&!a.equals(this.center);if(e||f||d){d||this.events.triggerEvent("movestart",{zoomChanged:e});f&&(!e&&this.center&&this.centerLayerContainer(a), + this.center=a.clone());a=e?this.getResolutionForZoom(b):this.getResolution();if(e||null==this.layerContainerOrigin){this.layerContainerOrigin=this.getCachedCenter();this.layerContainerOriginPx.x=0;this.layerContainerOriginPx.y=0;this.applyTransform();var f=this.getMaxExtent({restricted:!0}),h=f.getCenterLonLat(),g=this.center.lon-h.lon,h=h.lat-this.center.lat,k=Math.round(f.getWidth()/a),l=Math.round(f.getHeight()/a);this.minPx={x:(this.size.w-k)/2-g/a,y:(this.size.h-l)/2-h/a};this.maxPx={x:this.minPx.x+ + Math.round(f.getWidth()/a),y:this.minPx.y+Math.round(f.getHeight()/a)}}e&&(this.zoom=b,this.resolution=a);a=this.getExtent();this.baseLayer.visibility&&(this.baseLayer.moveTo(a,e,c.dragging),c.dragging||this.baseLayer.events.triggerEvent("moveend",{zoomChanged:e}));a=this.baseLayer.getExtent();for(b=this.layers.length-1;0<=b;--b)f=this.layers[b],f===this.baseLayer||f.isBaseLayer||(g=f.calculateInRange(),f.inRange!=g&&((f.inRange=g)||f.display(!1),this.events.triggerEvent("changelayer",{layer:f,property:"visibility"})), + g&&f.visibility&&(f.moveTo(a,e,c.dragging),c.dragging||f.events.triggerEvent("moveend",{zoomChanged:e})));this.events.triggerEvent("move");d||this.events.triggerEvent("moveend");if(e){b=0;for(c=this.popups.length;b=this.down.xy.distanceTo(a.xy))&&this.touch&&this.down.touches.length===this.last.touches.length){a=0;for(var c=this.down.touches.length;athis.pixelTolerance){b=!1;break}}return b},getTouchDistance:function(a,b){return Math.sqrt(Math.pow(a.clientX-b.clientX,2)+Math.pow(a.clientY-b.clientY, + 2))},passesDblclickTolerance:function(a){a=!0;this.down&&this.first&&(a=this.down.xy.distanceTo(this.first.xy)<=this.dblclickTolerance);return a},clearTimer:function(){null!=this.timerId&&(window.clearTimeout(this.timerId),this.timerId=null);null!=this.rightclickTimerId&&(window.clearTimeout(this.rightclickTimerId),this.rightclickTimerId=null)},delayedCall:function(a){this.timerId=null;a&&this.callback("click",[a])},getEventInfo:function(a){var b;if(a.touches){var c=a.touches.length;b=Array(c);for(var d, + e=0;ethis.minRatio&&b<=this.maxRatio&&this.ovmap.getExtent().containsBounds(a)},updateOverview:function(){var a=this.map.getResolution(),b=this.ovmap.getResolution(),c=b/a;c>this.maxRatio?b=this.minRatio*a:c<=this.minRatio&&(b=this.maxRatio*a);this.ovmap.getProjection()!=this.map.getProjection()?(a=this.map.center.clone(),a.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject())):a=this.map.center;this.ovmap.setCenter(a, + this.ovmap.getZoomForResolution(b*this.resolutionFactor));this.updateRectToMap()},createMap:function(){var a=OpenLayers.Util.extend({controls:[],maxResolution:"auto",fallThrough:!1},this.mapOptions);this.ovmap=new OpenLayers.Map(this.mapDiv,a);this.ovmap.viewPortDiv.appendChild(this.extentRectangle);OpenLayers.Event.stopObserving(window,"unload",this.ovmap.unloadDestroy);this.ovmap.addLayers(this.layers);this.ovmap.zoomToMaxExtent();this.wComp=(this.wComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle, + "border-left-width"))+parseInt(OpenLayers.Element.getStyle(this.extentRectangle,"border-right-width")))?this.wComp:2;this.hComp=(this.hComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,"border-top-width"))+parseInt(OpenLayers.Element.getStyle(this.extentRectangle,"border-bottom-width")))?this.hComp:2;this.handlers.drag=new OpenLayers.Handler.Drag(this,{move:this.rectDrag,done:this.updateMapToRect},{map:this.ovmap});this.handlers.click=new OpenLayers.Handler.Click(this,{click:this.mapDivClick}, + {single:!0,"double":!1,stopSingle:!0,stopDouble:!0,pixelTolerance:1,map:this.ovmap});this.handlers.click.activate();this.rectEvents=new OpenLayers.Events(this,this.extentRectangle,null,!0);this.rectEvents.register("mouseover",this,function(a){this.handlers.drag.active||this.map.dragging||this.handlers.drag.activate()});this.rectEvents.register("mouseout",this,function(a){this.handlers.drag.dragging||this.handlers.drag.deactivate()});if(this.ovmap.getProjection()!=this.map.getProjection()){var a=this.map.getProjectionObject().getUnits()|| + this.map.units||this.map.baseLayer.units,b=this.ovmap.getProjectionObject().getUnits()||this.ovmap.units||this.ovmap.baseLayer.units;this.resolutionFactor=a&&b?OpenLayers.INCHES_PER_UNIT[a]/OpenLayers.INCHES_PER_UNIT[b]:1}},updateRectToMap:function(){var a;a=this.ovmap.getProjection()!=this.map.getProjection()?this.map.getExtent().transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject()):this.map.getExtent();(a=this.getRectBoundsFromMapBounds(a))&&this.setRectPxBounds(a)},updateMapToRect:function(){var a= + this.getMapBoundsFromRectBounds(this.rectPxBounds);this.ovmap.getProjection()!=this.map.getProjection()&&(a=a.transform(this.ovmap.getProjectionObject(),this.map.getProjectionObject()));this.map.panTo(a.getCenterLonLat())},setRectPxBounds:function(a){var b=Math.max(a.top,0),c=Math.max(a.left,0),d=Math.min(a.top+Math.abs(a.getHeight()),this.ovmap.size.h-this.hComp);a=Math.min(a.left+a.getWidth(),this.ovmap.size.w-this.wComp);var e=Math.max(a-c,0),f=Math.max(d-b,0);e=this.minResolution&&a<=this.maxResolution);return a},setIsBaseLayer:function(a){a!=this.isBaseLayer&&(this.isBaseLayer= + a,null!=this.map&&this.map.events.triggerEvent("changebaselayer",{layer:this}))},initResolutions:function(){var a,b,c,d={},e=!0;a=0;for(b=this.RESOLUTION_PROPERTIES.length;a=a||"number"!==typeof d&&"number"!==typeof c)){b=Array(a);var e=2;"number"==typeof c&&"number"==typeof d&&(e=Math.pow(d/c,1/(a-1)));var f;if("number"===typeof d)for(f=0;f=a&&(f=h,e=c),h<=a){g=h;break}c=f-g;c=0f)break;f=e}else if(this.resolutions[c]=a.count&& + this.removeGMapElements()}OpenLayers.Layer.EventPane.prototype.destroy.apply(this,arguments)},removeGMapElements:function(){var a=OpenLayers.Layer.Google.cache[this.map.id];if(a){var b=this.mapObject&&this.getMapContainer();b&&b.parentNode&&b.parentNode.removeChild(b);(b=a.termsOfUse)&&b.parentNode&&b.parentNode.removeChild(b);(a=a.poweredBy)&&a.parentNode&&a.parentNode.removeChild(a);this.mapObject&&(window.google&&google.maps&&google.maps.event&&google.maps.event.clearListeners)&&google.maps.event.clearListeners(this.mapObject, + "tilesloaded")}},removeMap:function(a){this.visibility&&this.mapObject&&this.setGMapVisibility(!1);var b=OpenLayers.Layer.Google.cache[a.id];b&&(1>=b.count?(this.removeGMapElements(),delete OpenLayers.Layer.Google.cache[a.id]):--b.count);delete this.termsOfUse;delete this.poweredBy;delete this.mapObject;delete this.dragObject;OpenLayers.Layer.EventPane.prototype.removeMap.apply(this,arguments)},getOLBoundsFromMapObjectBounds:function(a){var b=null;null!=a&&(b=a.getSouthWest(),a=a.getNorthEast(),this.sphericalMercator? + (b=this.forwardMercator(b.lng(),b.lat()),a=this.forwardMercator(a.lng(),a.lat())):(b=new OpenLayers.LonLat(b.lng(),b.lat()),a=new OpenLayers.LonLat(a.lng(),a.lat())),b=new OpenLayers.Bounds(b.lon,b.lat,a.lon,a.lat));return b},getWarningHTML:function(){return OpenLayers.i18n("googleWarning")},getMapObjectCenter:function(){return this.mapObject.getCenter()},getMapObjectZoom:function(){return this.mapObject.getZoom()},getLongitudeFromMapObjectLonLat:function(a){return this.sphericalMercator?this.forwardMercator(a.lng(), + a.lat()).lon:a.lng()},getLatitudeFromMapObjectLonLat:function(a){return this.sphericalMercator?this.forwardMercator(a.lng(),a.lat()).lat:a.lat()},getXFromMapObjectPixel:function(a){return a.x},getYFromMapObjectPixel:function(a){return a.y},CLASS_NAME:"OpenLayers.Layer.Google"});OpenLayers.Layer.Google.cache={}; +OpenLayers.Layer.Google.v2={termsOfUse:null,poweredBy:null,dragObject:null,loadMapObject:function(){this.type||(this.type=G_NORMAL_MAP);var a,b,c,d=OpenLayers.Layer.Google.cache[this.map.id];if(d)a=d.mapObject,b=d.termsOfUse,c=d.poweredBy,++d.count;else{var d=this.map.viewPortDiv,e=document.createElement("div");e.id=this.map.id+"_GMap2Container";e.style.position="absolute";e.style.width="100%";e.style.height="100%";d.appendChild(e);try{a=new GMap2(e),b=e.lastChild,d.appendChild(b),b.style.zIndex= + "1100",b.style.right="",b.style.bottom="",b.className="olLayerGoogleCopyright",c=e.lastChild,d.appendChild(c),c.style.zIndex="1100",c.style.right="",c.style.bottom="",c.className="olLayerGooglePoweredBy gmnoprint"}catch(f){throw f;}OpenLayers.Layer.Google.cache[this.map.id]={mapObject:a,termsOfUse:b,poweredBy:c,count:1}}this.mapObject=a;this.termsOfUse=b;this.poweredBy=c;-1===OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),this.type)&&this.mapObject.addMapType(this.type);"function"==typeof a.getDragObject? + this.dragObject=a.getDragObject():this.dragPanMapObject=null;!1===this.isBaseLayer&&this.setGMapVisibility("none"!==this.div.style.display)},onMapResize:function(){if(this.visibility&&this.mapObject.isLoaded())this.mapObject.checkResize();else{if(!this._resized)var a=this,b=GEvent.addListener(this.mapObject,"load",function(){GEvent.removeListener(b);delete a._resized;a.mapObject.checkResize();a.moveTo(a.map.getCenter(),a.map.getZoom())});this._resized=!0}},setGMapVisibility:function(a){var b=OpenLayers.Layer.Google.cache[this.map.id]; + if(b){var c=this.mapObject.getContainer();!0===a?(this.mapObject.setMapType(this.type),c.style.display="",this.termsOfUse.style.left="",this.termsOfUse.style.display="",this.poweredBy.style.display="",b.displayed=this.id):(b.displayed===this.id&&delete b.displayed,b.displayed||(c.style.display="none",this.termsOfUse.style.display="none",this.termsOfUse.style.left="-9999px",this.poweredBy.style.display="none"))}},getMapContainer:function(){return this.mapObject.getContainer()},getMapObjectBoundsFromOLBounds:function(a){var b= + null;null!=a&&(b=this.sphericalMercator?this.inverseMercator(a.bottom,a.left):new OpenLayers.LonLat(a.bottom,a.left),a=this.sphericalMercator?this.inverseMercator(a.top,a.right):new OpenLayers.LonLat(a.top,a.right),b=new GLatLngBounds(new GLatLng(b.lat,b.lon),new GLatLng(a.lat,a.lon)));return b},setMapObjectCenter:function(a,b){this.mapObject.setCenter(a,b)},dragPanMapObject:function(a,b){this.dragObject.moveBy(new GSize(-a,b))},getMapObjectLonLatFromMapObjectPixel:function(a){return this.mapObject.fromContainerPixelToLatLng(a)}, + getMapObjectPixelFromMapObjectLonLat:function(a){return this.mapObject.fromLatLngToContainerPixel(a)},getMapObjectZoomFromMapObjectBounds:function(a){return this.mapObject.getBoundsZoomLevel(a)},getMapObjectLonLatFromLonLat:function(a,b){var c;this.sphericalMercator?(c=this.inverseMercator(a,b),c=new GLatLng(c.lat,c.lon)):c=new GLatLng(b,a);return c},getMapObjectPixelFromXY:function(a,b){return new GPoint(a,b)}};OpenLayers.Format.XML=OpenLayers.Class(OpenLayers.Format,{namespaces:null,namespaceAlias:null,defaultPrefix:null,readers:{},writers:{},xmldom:null,initialize:function(a){window.ActiveXObject&&(this.xmldom=new ActiveXObject("Microsoft.XMLDOM"));OpenLayers.Format.prototype.initialize.apply(this,[a]);this.namespaces=OpenLayers.Util.extend({},this.namespaces);this.namespaceAlias={};for(var b in this.namespaces)this.namespaceAlias[this.namespaces[b]]=b},destroy:function(){this.xmldom=null;OpenLayers.Format.prototype.destroy.apply(this, + arguments)},setNamespace:function(a,b){this.namespaces[a]=b;this.namespaceAlias[b]=a},read:function(a){var b=a.indexOf("<");0this.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:b=a<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:b= + a>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:b=a>=this.lowerBoundary&&a<=this.upperBoundary;break;case OpenLayers.Filter.Comparison.LIKE:b=RegExp(this.value,"gi").test(a);break;case OpenLayers.Filter.Comparison.IS_NULL:b=null===a}return b},value2regex:function(a,b,c){if("."==a)throw Error("'.' is an unsupported wildCard character for OpenLayers.Filter.Comparison");a=a?a:"*";b=b?b:".";this.value=this.value.replace(RegExp("\\"+(c?c:"!")+"(.|$)","g"),"\\$1");this.value=this.value.replace(RegExp("\\"+ + b,"g"),".");this.value=this.value.replace(RegExp("\\"+a,"g"),".*");this.value=this.value.replace(RegExp("\\\\.\\*","g"),"\\"+a);return this.value=this.value.replace(RegExp("\\\\\\.","g"),"\\"+b)},regex2value:function(){var a=this.value,a=a.replace(/!/g,"!!"),a=a.replace(/(\\)?\\\./g,function(a,c){return c?a:"!."}),a=a.replace(/(\\)?\\\*/g,function(a,c){return c?a:"!*"}),a=a.replace(/\\\\/g,"\\");return a=a.replace(/\.\*/g,"*")},clone:function(){return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison, + this)},CLASS_NAME:"OpenLayers.Filter.Comparison"});OpenLayers.Filter.Comparison.EQUAL_TO="==";OpenLayers.Filter.Comparison.NOT_EQUAL_TO="!=";OpenLayers.Filter.Comparison.LESS_THAN="<";OpenLayers.Filter.Comparison.GREATER_THAN=">";OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO="<=";OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO=">=";OpenLayers.Filter.Comparison.BETWEEN="..";OpenLayers.Filter.Comparison.LIKE="~";OpenLayers.Filter.Comparison.IS_NULL="NULL";OpenLayers.Format.Filter=OpenLayers.Class(OpenLayers.Format.XML.VersionedOGC,{defaultVersion:"1.0.0",CLASS_NAME:"OpenLayers.Format.Filter"});OpenLayers.Filter.Function=OpenLayers.Class(OpenLayers.Filter,{name:null,params:null,CLASS_NAME:"OpenLayers.Filter.Function"});OpenLayers.Date={dateRegEx:/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))|Z)?$/,toISOString:function(){return"toISOString"in Date.prototype?function(a){return a.toISOString()}:function(a){return isNaN(a.getTime())?"Invalid Date":a.getUTCFullYear()+"-"+OpenLayers.Number.zeroPad(a.getUTCMonth()+1,2)+"-"+OpenLayers.Number.zeroPad(a.getUTCDate(),2)+"T"+OpenLayers.Number.zeroPad(a.getUTCHours(),2)+":"+OpenLayers.Number.zeroPad(a.getUTCMinutes(), + 2)+":"+OpenLayers.Number.zeroPad(a.getUTCSeconds(),2)+"."+OpenLayers.Number.zeroPad(a.getUTCMilliseconds(),3)+"Z"}}(),parse:function(a){var b;if((a=a.match(this.dateRegEx))&&(a[1]||a[7])){b=parseInt(a[1],10)||0;var c=parseInt(a[2],10)-1||0,d=parseInt(a[3],10)||1;b=new Date(Date.UTC(b,c,d));if(c=a[7]){var d=parseInt(a[4],10),e=parseInt(a[5],10),f=parseFloat(a[6]),g=f|0,f=Math.round(1E3*(f-g));b.setUTCHours(d,e,g,f);"Z"!==c&&(c=parseInt(c,10),a=parseInt(a[8],10)||0,a=-1E3*(60*60*c+60*a),b=new Date(b.getTime()+ + a))}}else b=new Date("invalid");return b}};OpenLayers.Format.Filter.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ogc:"http://www.opengis.net/ogc",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"ogc",schemaLocation:null,initialize:function(a){OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},read:function(a){var b={};this.readers.ogc.Filter.apply(this,[a,b]);return b.filter},readers:{ogc:{_expression:function(a){for(var b="",c=a.firstChild;c;c= + c.nextSibling)switch(c.nodeType){case 1:a=this.readNode(c);a.property?b+="${"+a.property+"}":void 0!==a.value&&(b+=a.value);break;case 3:case 4:b+=c.nodeValue}return b},Filter:function(a,b){var c={fids:[],filters:[]};this.readChildNodes(a,c);0":"PropertyIsGreaterThan","<=":"PropertyIsLessThanOrEqualTo",">=":"PropertyIsGreaterThanOrEqualTo","..":"PropertyIsBetween","~":"PropertyIsLike",NULL:"PropertyIsNull",BBOX:"BBOX",DWITHIN:"DWITHIN",WITHIN:"WITHIN",CONTAINS:"CONTAINS",INTERSECTS:"INTERSECTS",FID:"_featureIds"},CLASS_NAME:"OpenLayers.Format.Filter.v1"});OpenLayers.Geometry=OpenLayers.Class({id:null,parent:null,bounds:null,initialize:function(){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},destroy:function(){this.bounds=this.id=null},clone:function(){return new OpenLayers.Geometry},setBounds:function(a){a&&(this.bounds=a.clone())},clearBounds:function(){this.bounds=null;this.parent&&this.parent.clearBounds()},extendBounds:function(a){this.getBounds()?this.bounds.extend(a):this.setBounds(a)},getBounds:function(){null==this.bounds&&this.calculateBounds(); + return this.bounds},calculateBounds:function(){},distanceTo:function(a,b){},getVertices:function(a){},atPoint:function(a,b,c){var d=!1;null!=this.getBounds()&&null!=a&&(b=null!=b?b:0,c=null!=c?c:0,d=(new OpenLayers.Bounds(this.bounds.left-b,this.bounds.bottom-c,this.bounds.right+b,this.bounds.top+c)).containsLonLat(a));return d},getLength:function(){return 0},getArea:function(){return 0},getCentroid:function(){return null},toString:function(){return OpenLayers.Format&&OpenLayers.Format.WKT?OpenLayers.Format.WKT.prototype.write(new OpenLayers.Feature.Vector(this)): + Object.prototype.toString.call(this)},CLASS_NAME:"OpenLayers.Geometry"});OpenLayers.Geometry.fromWKT=function(a){var b;if(OpenLayers.Format&&OpenLayers.Format.WKT){var c=OpenLayers.Geometry.fromWKT.format;c||(c=new OpenLayers.Format.WKT,OpenLayers.Geometry.fromWKT.format=c);a=c.read(a);if(a instanceof OpenLayers.Feature.Vector)b=a.geometry;else if(OpenLayers.Util.isArray(a)){b=a.length;for(var c=Array(b),d=0;d=f&&0<=n&&1>=n)&&(d?(h=a.x1+f*h,n=a.y1+f*k,e=new OpenLayers.Geometry.Point(h,n)):e=!0));if(c)if(e){if(d)a:for(a=[a,b],b=0;2>b;++b)for(f=a[b],k=1;3>k;++k)if(h=f["x"+k],n=f["y"+k],d=Math.sqrt(Math.pow(h-e.x,2)+Math.pow(n-e.y,2)),db;++b)for(h=a[b],n=a[(b+1)%2],k=1;3>k;++k)if(f={x:h["x"+k],y:h["y"+k]},g=OpenLayers.Geometry.distanceToSegment(f,n),g.distance=m||(1<=m?(e=g,f=h):(e+=m*k,f+=m*l));return{distance:Math.pow(e-c,2)+Math.pow(f-d,2),x:e,y:f,along:m}};OpenLayers.Geometry.Point=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,initialize:function(a,b){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=parseFloat(a);this.y=parseFloat(b)},clone:function(a){null==a&&(a=new OpenLayers.Geometry.Point(this.x,this.y));OpenLayers.Util.applyDefaults(a,this);return a},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x,this.y)},distanceTo:function(a,b){var c=!(b&&!1===b.edge)&&b&&b.details,d,e,f,g,h;a instanceof +OpenLayers.Geometry.Point?(e=this.x,f=this.y,g=a.x,h=a.y,d=Math.sqrt(Math.pow(e-g,2)+Math.pow(f-h,2)),d=c?{x0:e,y0:f,x1:g,y1:h,distance:d}:d):(d=a.distanceTo(this,b),c&&(d={x0:d.x1,y0:d.y1,x1:d.x0,y1:d.y0,distance:d.distance}));return d},equals:function(a){var b=!1;null!=a&&(b=this.x==a.x&&this.y==a.y||isNaN(this.x)&&isNaN(this.y)&&isNaN(a.x)&&isNaN(a.y));return b},toShortString:function(){return this.x+", "+this.y},move:function(a,b){this.x+=a;this.y+=b;this.clearBounds()},rotate:function(a,b){a*= + Math.PI/180;var c=this.distanceTo(b),d=a+Math.atan2(this.y-b.y,this.x-b.x);this.x=b.x+c*Math.cos(d);this.y=b.y+c*Math.sin(d);this.clearBounds()},getCentroid:function(){return new OpenLayers.Geometry.Point(this.x,this.y)},resize:function(a,b,c){this.x=b.x+a*(void 0==c?1:c)*(this.x-b.x);this.y=b.y+a*(this.y-b.y);this.clearBounds();return this},intersects:function(a){var b=!1;return b="OpenLayers.Geometry.Point"==a.CLASS_NAME?this.equals(a):a.intersects(this)},transform:function(a,b){a&&b&&(OpenLayers.Projection.transform(this, + a,b),this.bounds=null);return this},getVertices:function(a){return[this]},CLASS_NAME:"OpenLayers.Geometry.Point"});OpenLayers.Geometry.Collection=OpenLayers.Class(OpenLayers.Geometry,{components:null,componentTypes:null,initialize:function(a){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.components=[];null!=a&&this.addComponents(a)},destroy:function(){this.components.length=0;this.components=null;OpenLayers.Geometry.prototype.destroy.apply(this,arguments)},clone:function(){for(var a=eval("new "+this.CLASS_NAME+"()"),b=0,c=this.components.length;bf)break;if(!(k.x2Math.max(g,h)||Math.max(l,m)h&&(k>l.y1&&kl.y2))break;e=c?{distance:e.distance,x0:e.x,y0:e.y,x1:h,y1:k}:e.distance}else if(a instanceof OpenLayers.Geometry.LineString){var g=this.getSortedSegments(),h=a.getSortedSegments(),p,q,r=h.length,s={point:!0},m=0,n=g.length;a:for(;mb.length)return this;var c=function(a,b,d,k){for(var l=0,m=0,n=b,p;nl&&(l=p,m=n)}l>k&&m!=b&&(e.push(m),c(a,b,m,k),c(a,m,d,k))},d=b.length-1,e=[];e.push(0);for(e.push(d);b[0].equals(b[d]);)d--,e.push(d);c(b,0,d,a);a=[];e.sort(function(a,b){return a-b});for(d=0;d=a)return this.components[0].clone();if(2=g&&c<=h||g>=h&&c<=g&&c>=h)){l=-1;break}}else{k=b((a-f)*((h-g)/(f-e))+h,14);if(k== + c&&(e=e&&a<=f||e>f&&a<=e&&a>=f)){l=-1;break}k<=c||g!=h&&(kMath.max(g,h))||(e=e&&af&&a=f)&&++l}return-1==l?1:!!(l&1)},intersects:function(a){var b=!1;if("OpenLayers.Geometry.Point"==a.CLASS_NAME)b=this.containsPoint(a);else if("OpenLayers.Geometry.LineString"==a.CLASS_NAME)b=a.intersects(this);else if("OpenLayers.Geometry.LinearRing"==a.CLASS_NAME)b=OpenLayers.Geometry.LineString.prototype.intersects.apply(this,[a]);else for(var c=0,d=a.components.length;c< +d&&!(b=a.components[c].intersects(this));++c);return b},getVertices:function(a){return!0===a?[]:this.components.slice(0,this.components.length-1)},CLASS_NAME:"OpenLayers.Geometry.LinearRing"});OpenLayers.Geometry.Polygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LinearRing"],getArea:function(){var a=0;if(this.components&&0a?"0"+a:a}return'"'+a.getFullYear()+ + "-"+b(a.getMonth()+1)+"-"+b(a.getDate())+"T"+b(a.getHours())+":"+b(a.getMinutes())+":"+b(a.getSeconds())+'"'}},CLASS_NAME:"OpenLayers.Format.JSON"});OpenLayers.Format.GeoJSON=OpenLayers.Class(OpenLayers.Format.JSON,{ignoreExtraDims:!1,read:function(a,b,c){b=b?b:"FeatureCollection";var d=null,e=null,e="string"==typeof a?OpenLayers.Format.JSON.prototype.read.apply(this,[a,c]):a;if(!e)OpenLayers.Console.error("Bad JSON: "+a);else if("string"!=typeof e.type)OpenLayers.Console.error("Bad GeoJSON - no type: "+a);else if(this.isValidType(e,b))switch(b){case "Geometry":try{d=this.parseGeometry(e)}catch(f){OpenLayers.Console.error(f)}break;case "Feature":try{d= + this.parseFeature(e),d.type="Feature"}catch(g){OpenLayers.Console.error(g)}break;case "FeatureCollection":switch(d=[],e.type){case "Feature":try{d.push(this.parseFeature(e))}catch(h){d=null,OpenLayers.Console.error(h)}break;case "FeatureCollection":a=0;for(b=e.features.length;ad&&(e=~e);a[c]=e}return this.encodeUnsignedIntegers(a)},decodeSignedIntegers:function(a){a=this.decodeUnsignedIntegers(a);for(var b=a.length,c=0;c>1):d>>1}return a},encodeUnsignedIntegers:function(a){for(var b="",c=a.length,d=0;dg?(b.push(c),d=c=0):d+=5}return b},encodeFloat:function(a,b){a=Math.round(a*(b||1E5));return this.encodeSignedInteger(a)},decodeFloat:function(a,b){return this.decodeSignedInteger(a)/(b||1E5)},encodeSignedInteger:function(a){var b=a<<1;0>a&&(b=~b);return this.encodeUnsignedInteger(b)},decodeSignedInteger:function(a){a=this.decodeUnsignedInteger(a);return a&1?~(a>>1):a>>1},encodeUnsignedInteger:function(a){for(var b,c="";32<= + a;)b=(32|a&31)+63,c+=String.fromCharCode(b),a>>=5;return c+=String.fromCharCode(a+63)},decodeUnsignedInteger:function(a){for(var b=0,c=0,d=a.length,e=0;ef)break;c+=5}return b},CLASS_NAME:"OpenLayers.Format.EncodedPolyline"});OpenLayers.Control.Panel=OpenLayers.Class(OpenLayers.Control,{controls:null,autoActivate:!0,defaultControl:null,saveState:!1,allowDepress:!1,activeState:null,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,[a]);this.controls=[];this.activeState={}},destroy:function(){this.map&&this.map.events.unregister("buttonclick",this,this.onButtonClick);OpenLayers.Control.prototype.destroy.apply(this,arguments);for(var a,b=this.controls.length-1;0<=b;b--)a=this.controls[b],a.events&& +a.events.un({activate:this.iconOn,deactivate:this.iconOff}),a.panel_div=null;this.activeState=null},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){for(var a,b=0,c=this.controls.length;bthis.layer.opacity&&(a.filter="alpha(opacity="+100*this.layer.opacity+")");a.position="absolute"; + this.layerAlphaHack&&(a.paddingTop=a.height,a.height="0",a.width="100%");this.frame&&this.frame.appendChild(this.imgDiv)}return this.imgDiv},setImage:function(a){this.imgDiv=a},initImage:function(){if(this.url||this.imgDiv){this.events.triggerEvent("beforeload");this.layer.div.appendChild(this.getTile());this.events.triggerEvent(this._loadEvent);var a=this.getImage(),b=a.getAttribute("src")||"";this.url&&OpenLayers.Util.isEquivalentUrl(b,this.url)?this._loadTimeout=window.setTimeout(OpenLayers.Function.bind(this.onImageLoad, + this),0):(this.stopLoading(),this.crossOriginKeyword&&a.removeAttribute("crossorigin"),OpenLayers.Event.observe(a,"load",OpenLayers.Function.bind(this.onImageLoad,this)),OpenLayers.Event.observe(a,"error",OpenLayers.Function.bind(this.onImageError,this)),this.imageReloadAttempts=0,this.setImgSrc(this.url))}else this.isLoading=!1},setImgSrc:function(a){var b=this.imgDiv;a?(b.style.visibility="hidden",b.style.opacity=0,this.crossOriginKeyword&&("data:"!==a.substr(0,5)?b.setAttribute("crossorigin",this.crossOriginKeyword): + b.removeAttribute("crossorigin")),b.src=a):(this.stopLoading(),this.imgDiv=null,b.parentNode&&b.parentNode.removeChild(b))},getTile:function(){return this.frame?this.frame:this.getImage()},createBackBuffer:function(){if(this.imgDiv&&!this.isLoading){var a;this.frame?(a=this.frame.cloneNode(!1),a.appendChild(this.imgDiv)):a=this.imgDiv;this.imgDiv=null;return a}},onImageLoad:function(){var a=this.imgDiv;this.stopLoading();a.style.visibility="inherit";a.style.opacity=this.layer.opacity;this.isLoading= + !1;this.canvasContext=null;this.events.triggerEvent("loadend");!0===this.layerAlphaHack&&(a.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+a.src+"', sizingMethod='scale')")},onImageError:function(){var a=this.imgDiv;null!=a.src&&(this.imageReloadAttempts++,this.imageReloadAttempts<=OpenLayers.IMAGE_RELOAD_ATTEMPTS?this.setImgSrc(this.layer.getURL(this.bounds)):(OpenLayers.Element.addClass(a,"olImageLoadError"),this.events.triggerEvent("loaderror"),this.onImageLoad()))},stopLoading:function(){OpenLayers.Event.stopObservingElement(this.imgDiv); + window.clearTimeout(this._loadTimeout);delete this._loadTimeout},getCanvasContext:function(){if(OpenLayers.CANVAS_SUPPORTED&&this.imgDiv&&!this.isLoading){if(!this.canvasContext){var a=document.createElement("canvas");a.width=this.size.w;a.height=this.size.h;this.canvasContext=a.getContext("2d");this.canvasContext.drawImage(this.imgDiv,0,0)}return this.canvasContext}},CLASS_NAME:"OpenLayers.Tile.Image"}); +OpenLayers.Tile.Image.IMAGE=function(){var a=new Image;a.className="olTileImage";a.galleryImg="no";return a}();OpenLayers.Layer.Grid=OpenLayers.Class(OpenLayers.Layer.HTTPRequest,{tileSize:null,tileOriginCorner:"bl",tileOrigin:null,tileOptions:null,tileClass:OpenLayers.Tile.Image,grid:null,singleTile:!1,ratio:1.5,buffer:0,transitionEffect:"resize",numLoadingTiles:0,serverResolutions:null,loading:!1,backBuffer:null,gridResolution:null,backBufferResolution:null,backBufferLonLat:null,backBufferTimerId:null,removeBackBufferDelay:null,className:null,gridLayout:null,rowSign:null,transitionendEvents:["transitionend", + "webkitTransitionEnd","otransitionend","oTransitionEnd"],initialize:function(a,b,c,d){OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,arguments);this.grid=[];this._removeBackBuffer=OpenLayers.Function.bind(this.removeBackBuffer,this);this.initProperties();this.rowSign="t"===this.tileOriginCorner.substr(0,1)?1:-1},initProperties:function(){void 0===this.options.removeBackBufferDelay&&(this.removeBackBufferDelay=this.singleTile?0:2500);void 0===this.options.className&&(this.className=this.singleTile? + "olLayerGridSingleTile":"olLayerGrid")},setMap:function(a){OpenLayers.Layer.HTTPRequest.prototype.setMap.call(this,a);OpenLayers.Element.addClass(this.div,this.className)},removeMap:function(a){this.removeBackBuffer()},destroy:function(){this.removeBackBuffer();this.clearGrid();this.tileSize=this.grid=null;OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this,arguments)},clearGrid:function(){if(this.grid){for(var a=0,b=this.grid.length;ab)break;b=d;f=e}a=f}return a},getServerZoom:function(){var a=this.getServerResolution();return this.serverResolutions?OpenLayers.Util.indexOf(this.serverResolutions,a):this.map.getZoomForResolution(a)+(this.zoomOffset||0)},applyBackBuffer:function(a){null!==this.backBufferTimerId&&this.removeBackBuffer();var b=this.backBuffer;if(!b){b= + this.createBackBuffer();if(!b)return;a===this.gridResolution?this.div.insertBefore(b,this.div.firstChild):this.map.baseLayer.div.parentNode.insertBefore(b,this.map.baseLayer.div);this.backBuffer=b;var c=this.grid[0][0].bounds;this.backBufferLonLat={lon:c.left,lat:c.top};this.backBufferResolution=this.gridResolution}for(var c=this.backBufferResolution/a,d=b.childNodes,e,f=d.length-1;0<=f;--f)e=d[f],e.style.top=(c*e._i*e._h|0)+"px",e.style.left=(c*e._j*e._w|0)+"px",e.style.width=Math.round(c*e._w)+ + "px",e.style.height=Math.round(c*e._h)+"px";a=this.getViewPortPxFromLonLat(this.backBufferLonLat,a);c=this.map.layerContainerOriginPx.y;b.style.left=Math.round(a.x-this.map.layerContainerOriginPx.x)+"px";b.style.top=Math.round(a.y-c)+"px"},createBackBuffer:function(){var a;if(0=a.bottom-h*this.buffer||n-d.w*(a-1))this.shiftColumn(!0,d);else if(c<-d.w*a)this.shiftColumn(!1,d);else if(b>-d.h*(a-1))this.shiftRow(!0,d);else if(b<-d.h*a)this.shiftRow(!1,d);else break}},shiftRow:function(a,b){var c=this.grid,d=a?0:c.length-1,e=a?-1:1;this.gridLayout.startrow+=e*this.rowSign;for(var f=c[d],g=c[a?"pop":"shift"](),h=0,k=g.length;ha;){var e=this.grid.pop();c=0;for(d=e.length;c + b;)e=this.grid[c],f=e.pop(),this.destroyTile(f)},onMapResize:function(){this.singleTile&&(this.clearGrid(),this.setTileSize())},getTileBounds:function(a){var b=this.maxExtent,c=this.getResolution(),d=c*this.tileSize.w,c=c*this.tileSize.h,e=this.getLonLatFromViewPortPx(a);a=b.left+d*Math.floor((e.lon-b.left)/d);b=b.bottom+c*Math.floor((e.lat-b.bottom)/c);return new OpenLayers.Bounds(a,b,a+d,b+c)},CLASS_NAME:"OpenLayers.Layer.Grid"});OpenLayers.Format.ArcXML=OpenLayers.Class(OpenLayers.Format.XML,{fontStyleKeys:"antialiasing blockout font fontcolor fontsize fontstyle glowing interval outline printmode shadow transparency".split(" "),request:null,response:null,initialize:function(a){this.request=new OpenLayers.Format.ArcXML.Request;this.response=new OpenLayers.Format.ArcXML.Response;if(a)if("feature"==a.requesttype){this.request.get_image=null;var b=this.request.get_feature.query;this.addCoordSys(b.featurecoordsys,a.featureCoordSys); + this.addCoordSys(b.filtercoordsys,a.filterCoordSys);a.polygon?(b.isspatial=!0,b.spatialfilter.polygon=a.polygon):a.envelope&&(b.isspatial=!0,b.spatialfilter.envelope={minx:0,miny:0,maxx:0,maxy:0},this.parseEnvelope(b.spatialfilter.envelope,a.envelope))}else"image"==a.requesttype?(this.request.get_feature=null,b=this.request.get_image.properties,this.parseEnvelope(b.envelope,a.envelope),this.addLayers(b.layerlist,a.layers),this.addImageSize(b.imagesize,a.tileSize),this.addCoordSys(b.featurecoordsys, + a.featureCoordSys),this.addCoordSys(b.filtercoordsys,a.filterCoordSys)):this.request=null;OpenLayers.Format.XML.prototype.initialize.apply(this,[a])},parseEnvelope:function(a,b){b&&4==b.length&&(a.minx=b[0],a.miny=b[1],a.maxx=b[2],a.maxy=b[3])},addLayers:function(a,b){for(var c=0,d=b.length;cg.where.length)continue;var h=null,h="boolean"==typeof g.spatialfilter&&g.spatialfilter?this.createElementNS("","SPATIALQUERY"):this.createElementNS("","QUERY");h.setAttribute("where",g.where);"number"==typeof g.accuracy&&0g.featurelimit&&h.setAttribute("featurelimit", + g.featurelimit);"string"==typeof g.subfields&&"#ALL#"!=g.subfields&&h.setAttribute("subfields",g.subfields);"string"==typeof g.joinexpression&&0arguments.length&&(k=!0);this._async=k;var r=this, + s=this.readyState,t;h&&k&&(t=function(){s!=b.DONE&&(e(r),r.abort())},window.attachEvent("onunload",t));b.onopen&&b.onopen.apply(this,arguments);4b.UNSENT&&(this._aborted=!0);this._object.abort();e(this);this.readyState=b.UNSENT;delete this._data};b.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders()};b.prototype.getResponseHeader=function(a){return this._object.getResponseHeader(a)};b.prototype.setRequestHeader=function(a,b){this._headers||(this._headers={});this._headers[a]=b;return this._object.setRequestHeader(a,b)}; + b.prototype.addEventListener=function(a,b,c){for(var d=0,e;e=this._listeners[d];d++)if(e[0]==a&&e[1]==b&&e[2]==c)return;this._listeners.push([a,b,c])};b.prototype.removeEventListener=function(a,b,c){for(var d=0,e;(e=this._listeners[d])&&(e[0]!=a||e[1]!=b||e[2]!=c);d++);e&&this._listeners.splice(d,1)};b.prototype.dispatchEvent=function(a){a={type:a.type,target:this,currentTarget:this,eventPhase:2,bubbles:a.bubbles,cancelable:a.cancelable,timeStamp:a.timeStamp,stopPropagation:function(){},preventDefault:function(){}, + initEvent:function(){}};"readystatechange"==a.type&&this.onreadystatechange&&(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[a]);for(var b=0,c;c=this._listeners[b];b++)c[0]!=a.type||c[2]||(c[1].handleEvent||c[1]).apply(this,[a])};b.prototype.toString=function(){return"[object XMLHttpRequest]"};b.toString=function(){return"[XMLHttpRequest]"};window.Function.prototype.apply||(window.Function.prototype.apply=function(a,b){b||(b=[]);a.__func=this;a.__func(b[0],b[1],b[2],b[3], + b[4]);delete a.__func});OpenLayers.Request||(OpenLayers.Request={});OpenLayers.Request.XMLHttpRequest=b})();OpenLayers.ProxyHost="";OpenLayers.Request||(OpenLayers.Request={}); +OpenLayers.Util.extend(OpenLayers.Request,{DEFAULT_CONFIG:{method:"GET",url:window.location.href,async:!0,user:void 0,password:void 0,params:null,proxy:OpenLayers.ProxyHost,headers:{},data:null,callback:function(){},success:null,failure:null,scope:null},URL_SPLIT_REGEX:/([^:]*:)\/\/([^:]*:?[^@]*@)?([^:\/\?]*):?([^\/\?]*)/,events:new OpenLayers.Events(this),makeSameOrigin:function(a,b){var c=0!==a.indexOf("http"),d=!c&&a.match(this.URL_SPLIT_REGEX);if(d){var e=window.location,c=d[1]==e.protocol&&d[3]== + e.hostname,d=d[4],e=e.port;if(80!=d&&""!=d||"80"!=e&&""!=e)c=c&&d==e}c||b&&(a="function"==typeof b?b(a):b+encodeURIComponent(a));return a},issue:function(a){var b=OpenLayers.Util.extend(this.DEFAULT_CONFIG,{proxy:OpenLayers.ProxyHost});a=a||{};a.headers=a.headers||{};a=OpenLayers.Util.applyDefaults(a,b);a.headers=OpenLayers.Util.applyDefaults(a.headers,b.headers);var b=!1,c;for(c in a.headers)a.headers.hasOwnProperty(c)&&"x-requested-with"===c.toLowerCase()&&(b=!0);!1===b&&(a.headers["X-Requested-With"]= + "XMLHttpRequest");var d=new OpenLayers.Request.XMLHttpRequest,e=OpenLayers.Util.urlAppend(a.url,OpenLayers.Util.getParameterString(a.params||{})),e=OpenLayers.Request.makeSameOrigin(e,a.proxy);d.open(a.method,e,a.async,a.user,a.password);for(var f in a.headers)d.setRequestHeader(f,a.headers[f]);var g=this.events,h=this;d.onreadystatechange=function(){d.readyState==OpenLayers.Request.XMLHttpRequest.DONE&&!1!==g.triggerEvent("complete",{request:d,config:a,requestUrl:e})&&h.runCallbacks({request:d,config:a, + requestUrl:e})};!1===a.async?d.send(a.data):window.setTimeout(function(){0!==d.readyState&&d.send(a.data)},0);return d},runCallbacks:function(a){var b=a.request,c=a.config,d=c.scope?OpenLayers.Function.bind(c.callback,c.scope):c.callback,e;c.success&&(e=c.scope?OpenLayers.Function.bind(c.success,c.scope):c.success);var f;c.failure&&(f=c.scope?OpenLayers.Function.bind(c.failure,c.scope):c.failure);"file:"==OpenLayers.Util.createUrlObject(c.url).protocol&&b.responseText&&(b.status=200);d(b);if(!b.status|| + 200<=b.status&&300>b.status)this.events.triggerEvent("success",a),e&&e(b);b.status&&(200>b.status||300<=b.status)&&(this.events.triggerEvent("failure",a),f&&f(b))},GET:function(a){a=OpenLayers.Util.extend(a,{method:"GET"});return OpenLayers.Request.issue(a)},POST:function(a){a=OpenLayers.Util.extend(a,{method:"POST"});a.headers=a.headers?a.headers:{};"CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(a.headers)||(a.headers["Content-Type"]="application/xml");return OpenLayers.Request.issue(a)},PUT:function(a){a= + OpenLayers.Util.extend(a,{method:"PUT"});a.headers=a.headers?a.headers:{};"CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(a.headers)||(a.headers["Content-Type"]="application/xml");return OpenLayers.Request.issue(a)},DELETE:function(a){a=OpenLayers.Util.extend(a,{method:"DELETE"});return OpenLayers.Request.issue(a)},HEAD:function(a){a=OpenLayers.Util.extend(a,{method:"HEAD"});return OpenLayers.Request.issue(a)},OPTIONS:function(a){a=OpenLayers.Util.extend(a,{method:"OPTIONS"});return OpenLayers.Request.issue(a)}});OpenLayers.Layer.ArcIMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{ClientVersion:"9.2",ServiceName:""},featureCoordSys:"4326",filterCoordSys:"4326",layers:null,async:!0,name:"ArcIMS",isBaseLayer:!0,DEFAULT_OPTIONS:{tileSize:new OpenLayers.Size(512,512),featureCoordSys:"4326",filterCoordSys:"4326",layers:null,isBaseLayer:!0,async:!0,name:"ArcIMS"},initialize:function(a,b,c){this.tileSize=new OpenLayers.Size(512,512);this.params=OpenLayers.Util.applyDefaults({ServiceName:c.serviceName}, + this.DEFAULT_PARAMS);this.options=OpenLayers.Util.applyDefaults(c,this.DEFAULT_OPTIONS);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[a,b,this.params,c]);this.transparent&&(this.isBaseLayer||(this.isBaseLayer=!1),"image/jpeg"==this.format&&(this.format=OpenLayers.Util.alphaHack()?"image/gif":"image/png"));null===this.options.layers&&(this.options.layers=[])},getURL:function(a){var b="";a=this.adjustBounds(a);a=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image", + envelope:a.toArray(),tileSize:this.tileSize}));a=new OpenLayers.Request.POST({url:this.getFullRequestString(),data:a.write(),async:!1});null!=a&&(b=a.responseXML,b&&b.documentElement||(b=a.responseText),b=(new OpenLayers.Format.ArcXML).read(b),b=this.getUrlOrImage(b.image.output));return b},getURLasync:function(a,b,c){a=this.adjustBounds(a);a=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:a.toArray(),tileSize:this.tileSize}));OpenLayers.Request.POST({url:this.getFullRequestString(), + async:!0,data:a.write(),callback:function(a){var e=a.responseXML;e&&e.documentElement||(e=a.responseText);a=(new OpenLayers.Format.ArcXML).read(e);b.call(c,this.getUrlOrImage(a.image.output))},scope:this})},getUrlOrImage:function(a){var b="";a.url?b=a.url:a.data&&(b="data:image/"+a.type+";base64,"+a.data);return b},setLayerQuery:function(a,b){for(var c=0;cOpenStreetMap contributors",sphericalMercator:!0,wrapDateLine:!0,tileOptions:null,initialize:function(a,b,c){OpenLayers.Layer.XYZ.prototype.initialize.apply(this,arguments);this.tileOptions= + OpenLayers.Util.extend({crossOriginKeyword:"anonymous"},this.options&&this.options.tileOptions)},clone:function(a){null==a&&(a=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions()));return a=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[a])},CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Renderer=OpenLayers.Class({container:null,root:null,extent:null,locked:!1,size:null,resolution:null,map:null,featureDx:0,initialize:function(a,b){this.container=OpenLayers.Util.getElement(a);OpenLayers.Util.extend(this,b)},destroy:function(){this.map=this.resolution=this.size=this.extent=this.container=null},supported:function(){return!1},setExtent:function(a,b){this.extent=a.clone();if(this.map.baseLayer&&this.map.baseLayer.wrapDateLine){var c=a.getWidth()/this.map.getExtent().getWidth(); + a=a.scale(1/c);this.extent=a.wrapDateLine(this.map.getMaxExtent()).scale(c)}b&&(this.resolution=null);return!0},setSize:function(a){this.size=a.clone();this.resolution=null},getResolution:function(){return this.resolution=this.resolution||this.map.getResolution()},drawFeature:function(a,b){null==b&&(b=a.style);if(a.geometry){var c=a.geometry.getBounds();if(c){var d;this.map.baseLayer&&this.map.baseLayer.wrapDateLine&&(d=this.map.getMaxExtent());c.intersectsBounds(this.extent,{worldBounds:d})?this.calculateFeatureDx(c, + d):b={display:"none"};c=this.drawGeometry(a.geometry,b,a.id);if("none"!=b.display&&b.label&&!1!==c){d=a.geometry.getCentroid();if(b.labelXOffset||b.labelYOffset){var e=isNaN(b.labelXOffset)?0:b.labelXOffset,f=isNaN(b.labelYOffset)?0:b.labelYOffset,g=this.getResolution();d.move(e*g,f*g)}this.drawText(a.id,b,d)}else this.removeText(a.id);return c}}},calculateFeatureDx:function(a,b){this.featureDx=0;if(b){var c=b.getWidth();this.featureDx=Math.round(((a.left+a.right)/2-(this.extent.left+this.extent.right)/ + 2)/c)*c}},drawGeometry:function(a,b,c){},drawText:function(a,b,c){},removeText:function(a){},clear:function(){},getFeatureIdFromEvent:function(a){},eraseFeatures:function(a){OpenLayers.Util.isArray(a)||(a=[a]);for(var b=0,c=a.length;bh.length||(a=this.getLocalXY(a),e=a[0],g=a[1],isNaN(e)||isNaN(g)))){this.canvas.lineCap="round";this.canvas.lineJoin="round";this.hitDetection&&(this.hitContext.lineCap="round",this.hitContext.lineJoin="round");if(b.graphicName in this.cachedSymbolBounds)d=this.cachedSymbolBounds[b.graphicName];else{d=new OpenLayers.Bounds;for(a=0;a=this.map.Z_INDEX_BASE.Feature?this.layer.setZIndex(a):this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer))},CLASS_NAME:"OpenLayers.Control.ModifyFeature"}); +OpenLayers.Control.ModifyFeature.RESHAPE=1;OpenLayers.Control.ModifyFeature.RESIZE=2;OpenLayers.Control.ModifyFeature.ROTATE=4;OpenLayers.Control.ModifyFeature.DRAG=8;OpenLayers.Layer.Bing=OpenLayers.Class(OpenLayers.Layer.XYZ,{key:null,serverResolutions:[156543.03390625,78271.516953125,39135.7584765625,19567.87923828125,9783.939619140625,4891.9698095703125,2445.9849047851562,1222.9924523925781,611.4962261962891,305.74811309814453,152.87405654907226,76.43702827453613,38.218514137268066,19.109257068634033,9.554628534317017,4.777314267158508,2.388657133579254,1.194328566789627,0.5971642833948135,0.29858214169740677,0.14929107084870338,0.07464553542435169],attributionTemplate:'
${copyrights}Terms of Use
', + metadata:null,protocolRegex:/^http:/i,type:"Road",culture:"en-US",metadataParams:null,tileOptions:null,protocol:~window.location.href.indexOf("http")?"":"http:",initialize:function(a){a=OpenLayers.Util.applyDefaults({sphericalMercator:!0},a);OpenLayers.Layer.XYZ.prototype.initialize.apply(this,[a.name||"Bing "+(a.type||this.type),null,a]);this.tileOptions=OpenLayers.Util.extend({crossOriginKeyword:"anonymous"},this.options.tileOptions);this.loadMetadata()},loadMetadata:function(){this._callbackId= + "_callback_"+this.id.replace(/\./g,"_");window[this._callbackId]=OpenLayers.Function.bind(OpenLayers.Layer.Bing.processMetadata,this);var a=OpenLayers.Util.applyDefaults({key:this.key,jsonp:this._callbackId,include:"ImageryProviders"},this.metadataParams),a=this.protocol+"//dev.virtualearth.net/REST/v1/Imagery/Metadata/"+this.type+"?"+OpenLayers.Util.getParameterString(a),b=document.createElement("script");b.type="text/javascript";b.src=a;b.id=this._callbackId;document.getElementsByTagName("head")[0].appendChild(b)}, + initLayer:function(){var a=this.metadata.resourceSets[0].resources[0],b=a.imageUrl.replace("{quadkey}","${quadkey}"),b=b.replace("{culture}",this.culture),b=b.replace(this.protocolRegex,this.protocol);this.url=[];for(var c=0;c=n.zoomMin)&&(b+=f.attribution+" ");a=a.brandLogoUri.replace(this.protocolRegex,this.protocol);this.attribution=OpenLayers.String.format(this.attributionTemplate,{type:this.type.toLowerCase(), + logo:a,copyrights:b});this.map&&this.map.events.triggerEvent("changelayer",{layer:this,property:"attribution"})}},setMap:function(){OpenLayers.Layer.XYZ.prototype.setMap.apply(this,arguments);this.map.events.register("moveend",this,this.updateAttribution)},clone:function(a){null==a&&(a=new OpenLayers.Layer.Bing(this.options));return a=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[a])},destroy:function(){this.map&&this.map.events.unregister("moveend",this,this.updateAttribution);OpenLayers.Layer.XYZ.prototype.destroy.apply(this, + arguments)},CLASS_NAME:"OpenLayers.Layer.Bing"});OpenLayers.Layer.Bing.processMetadata=function(a){this.metadata=a;this.initLayer();a=document.getElementById(this._callbackId);a.parentNode.removeChild(a);window[this._callbackId]=void 0;delete this._callbackId};OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:!0,initialize:function(a,b){this.styles={"default":new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]),select:new OpenLayers.Style(OpenLayers.Feature.Vector.style.select),temporary:new OpenLayers.Style(OpenLayers.Feature.Vector.style.temporary),"delete":new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"])};if(a instanceof OpenLayers.Style)this.styles["default"]=a,this.styles.select=a,this.styles.temporary=a,this.styles["delete"]= + a;else if("object"==typeof a)for(var c in a)if(a[c]instanceof OpenLayers.Style)this.styles[c]=a[c];else if("object"==typeof a[c])this.styles[c]=new OpenLayers.Style(a[c]);else{this.styles["default"]=new OpenLayers.Style(a);this.styles.select=new OpenLayers.Style(a);this.styles.temporary=new OpenLayers.Style(a);this.styles["delete"]=new OpenLayers.Style(a);break}OpenLayers.Util.extend(this,b)},destroy:function(){for(var a in this.styles)this.styles[a].destroy();this.styles=null},createSymbolizer:function(a, + b){a||(a=new OpenLayers.Feature.Vector);this.styles[b]||(b="default");a.renderIntent=b;var c={};this.extendDefault&&"default"!=b&&(c=this.styles["default"].createSymbolizer(a));return OpenLayers.Util.extend(c,this.styles[b].createSymbolizer(a))},addUniqueValueRules:function(a,b,c,d){var e=[],f;for(f in c)e.push(new OpenLayers.Rule({symbolizer:c[f],context:d,filter:new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,property:b,value:f})}));this.styles[a].addRules(e)},CLASS_NAME:"OpenLayers.StyleMap"});OpenLayers.Layer.Vector=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:!1,isFixed:!1,features:null,filter:null,selectedFeatures:null,unrenderedFeatures:null,reportError:!0,style:null,styleMap:null,strategies:null,protocol:null,renderers:["SVG","VML","Canvas"],renderer:null,rendererOptions:null,geometryType:null,drawn:!1,ratio:1,initialize:function(a,b){OpenLayers.Layer.prototype.initialize.apply(this,arguments);this.renderer&&this.renderer.supported()||this.assignRenderer();this.renderer&&this.renderer.supported()|| +(this.renderer=null,this.displayError());this.styleMap||(this.styleMap=new OpenLayers.StyleMap);this.features=[];this.selectedFeatures=[];this.unrenderedFeatures={};if(this.strategies)for(var c=0,d=this.strategies.length;cb?this.callback("down",[a,this.cumulative?Math.max(-this.maxDelta, + b):-1]):this.callback("up",[a,this.cumulative?Math.min(this.maxDelta,b):1]))},activate:function(a){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var b=this.wheelListener;OpenLayers.Event.observe(window,"DOMMouseScroll",b);OpenLayers.Event.observe(window,"mousewheel",b);OpenLayers.Event.observe(document,"mousewheel",b);return!0}return!1},deactivate:function(a){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){var b=this.wheelListener;OpenLayers.Event.stopObserving(window, + "DOMMouseScroll",b);OpenLayers.Event.stopObserving(window,"mousewheel",b);OpenLayers.Event.stopObserving(document,"mousewheel",b);return!0}return!1},CLASS_NAME:"OpenLayers.Handler.MouseWheel"});OpenLayers.Symbolizer=OpenLayers.Class({zIndex:0,initialize:function(a){OpenLayers.Util.extend(this,a)},clone:function(){return new (eval(this.CLASS_NAME))(OpenLayers.Util.extend({},this))},CLASS_NAME:"OpenLayers.Symbolizer"});OpenLayers.Symbolizer.Raster=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(a){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments)},CLASS_NAME:"OpenLayers.Symbolizer.Raster"});OpenLayers.Rule=OpenLayers.Class({id:null,name:null,title:null,description:null,context:null,filter:null,elseFilter:!1,symbolizer:null,symbolizers:null,minScaleDenominator:null,maxScaleDenominator:null,initialize:function(a){this.symbolizer={};OpenLayers.Util.extend(this,a);this.symbolizers&&delete this.symbolizer;this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_")},destroy:function(){for(var a in this.symbolizer)this.symbolizer[a]=null;this.symbolizer=null;delete this.symbolizers},evaluate:function(a){var b= + this.getContext(a),c=!0;if(this.minScaleDenominator||this.maxScaleDenominator)var d=a.layer.map.getScale();this.minScaleDenominator&&(c=d>=OpenLayers.Style.createLiteral(this.minScaleDenominator,b));c&&this.maxScaleDenominator&&(c=dthis.maxZIndex&&(this.maxZIndex=b)},getNextElement:function(a){a+=1;if(aa.left&&f.righta.left&&f.lefta.length)throw Error("At least two point features have to be added to create a line from");for(var c=Array(a.length-1),d,e,f,g=0,h=a.length;gthis.opacity&&a.setOpacity(this.opacity);this.map&&this.map.getExtent()&&(a.map=this.map,this.drawMarker(a))},removeMarker:function(a){this.markers&&this.markers.length&&(OpenLayers.Util.removeItem(this.markers,a),a.erase())},clearMarkers:function(){if(null!=this.markers)for(;0=a.maxResolution)return null;for(var c= + {node:this.getGeoTolerance(a.nodeTolerance,c),vertex:this.getGeoTolerance(a.vertexTolerance,c),edge:this.getGeoTolerance(a.edgeTolerance,c)},d=Math.max(c.node,c.vertex,c.edge),e={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY},f=!1,g=a.layer.features,h,k,l,m,n,p,q=this.precedence.length,r=new OpenLayers.LonLat(b.x,b.y),s=0,t=g.length;s=this.maxDepth)return!1;var c=OpenLayers.Util.extend({},b);c.depth++;for(var d=0,e=a.length;d=e.length)){switch(e.length){case 1:f=e[0];break;case 2:f=e[0];e=e[1];f=3==f.nodeType||4==f.nodeType?f:e;break;default:f=e[1]}if(3==f.nodeType||4==f.nodeType)if(d=d.prefix?d.nodeName.split(":")[1]:d.nodeName,f=OpenLayers.Util.getXmlNodeValue(f))f=f.replace(this.regExes.trimSpace,""),b[d]=f}return b},parseExtendedData:function(a){var b={},c,d,e,f,g=a.getElementsByTagName("Data");c=0;for(d=g.length;cc.status?(c=this.parseResponse(c,b.readOptions))&&!1!==c.success?(b.readOptions&&"object"==b.readOptions.output?OpenLayers.Util.extend(a,c):a.features=c,a.code=OpenLayers.Protocol.Response.SUCCESS):(a.code=OpenLayers.Protocol.Response.FAILURE,a.error=c):a.code=OpenLayers.Protocol.Response.FAILURE;b.callback.call(b.scope,a)}},parseResponse:function(a,b){var c=a.responseXML;c&&c.documentElement||(c=a.responseText);if(!c||0>=c.length)return null;c=null!==this.readFormat?this.readFormat.read(c): + this.format.read(c,b);if(!this.featureNS){var d=this.readFormat||this.format;this.featureNS=d.featureNS;d.autoConfig=!1;this.geometryName||this.setGeometryName(d.geometryName)}return c},commit:function(a,b){b=OpenLayers.Util.extend({},b);OpenLayers.Util.applyDefaults(b,this.options);var c=new OpenLayers.Protocol.Response({requestType:"commit",reqFeatures:a});c.priv=OpenLayers.Request.POST({url:b.url,headers:b.headers,data:this.format.write(a,b),callback:this.createCallback(this.handleCommit,c,b)}); + return c},handleCommit:function(a,b){if(b.callback){var c=a.priv,d=c.responseXML;d&&d.documentElement||(d=c.responseText);c=this.format.read(d)||{};a.insertIds=c.insertIds||[];c.success?a.code=OpenLayers.Protocol.Response.SUCCESS:(a.code=OpenLayers.Protocol.Response.FAILURE,a.error=c);b.callback.call(b.scope,a)}},filterDelete:function(a,b){b=OpenLayers.Util.extend({},b);OpenLayers.Util.applyDefaults(b,this.options);new OpenLayers.Protocol.Response({requestType:"commit"});var c=this.format.createElementNSPlus("wfs:Transaction", + {attributes:{service:"WFS",version:this.version}}),d=this.format.createElementNSPlus("wfs:Delete",{attributes:{typeName:(b.featureNS?this.featurePrefix+":":"")+b.featureType}});b.featureNS&&d.setAttribute("xmlns:"+this.featurePrefix,b.featureNS);var e=this.format.writeNode("ogc:Filter",a);d.appendChild(e);c.appendChild(d);c=OpenLayers.Format.XML.prototype.write.apply(this.format,[c]);return OpenLayers.Request.POST({url:this.url,callback:b.callback||function(){},data:c})},abort:function(a){a&&a.priv.abort()}, + CLASS_NAME:"OpenLayers.Protocol.WFS.v1"});OpenLayers.Handler.Feature=OpenLayers.Class(OpenLayers.Handler,{EVENTMAP:{click:{"in":"click",out:"clickout"},mousemove:{"in":"over",out:"out"},dblclick:{"in":"dblclick",out:null},mousedown:{"in":null,out:null},mouseup:{"in":null,out:null},touchstart:{"in":"click",out:"clickout"}},feature:null,lastFeature:null,down:null,up:null,clickTolerance:4,geometryTypes:null,stopClick:!0,stopDown:!0,stopUp:!1,initialize:function(a,b,c,d){OpenLayers.Handler.prototype.initialize.apply(this,[a,c,d]);this.layer= + b},touchstart:function(a){this.startTouch();return OpenLayers.Event.isMultiTouch(a)?!0:this.mousedown(a)},touchmove:function(a){OpenLayers.Event.preventDefault(a)},mousedown:function(a){if(OpenLayers.Event.isLeftClick(a)||OpenLayers.Event.isSingleTouch(a))this.down=a.xy;return this.handle(a)?!this.stopDown:!0},mouseup:function(a){this.up=a.xy;return this.handle(a)?!this.stopUp:!0},click:function(a){return this.handle(a)?!this.stopClick:!0},mousemove:function(a){if(!this.callbacks.over&&!this.callbacks.out)return!0; + this.handle(a);return!0},dblclick:function(a){return!this.handle(a)},geometryTypeMatches:function(a){return null==this.geometryTypes||-1=this.map.Z_INDEX_BASE.Feature?this.layer.setZIndex(a):this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer))},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.Layer.Vector.RootContainer=OpenLayers.Class(OpenLayers.Layer.Vector,{displayInLayerSwitcher:!1,layers:null,display:function(){},getFeatureFromEvent:function(a){for(var b=this.layers,c,d=0;df;)d=c.selectedFeatures[f],a&&a.except==d?++f:this.unselect(d)},clickFeature:function(a){this.hover||(-1c&&(d=!1);return d},CLASS_NAME:"OpenLayers.Handler.Point"});OpenLayers.Handler.Path=OpenLayers.Class(OpenLayers.Handler.Point,{line:null,maxVertices:null,doubleTouchTolerance:20,freehand:!1,freehandToggle:"shiftKey",timerId:null,redoStack:null,createFeature:function(a){a=this.layer.getLonLatFromViewPortPx(a);a=new OpenLayers.Geometry.Point(a.lon,a.lat);this.point=new OpenLayers.Feature.Vector(a);this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([this.point.geometry]));this.callback("create",[this.point.geometry,this.getSketch()]); + this.point.geometry.clearBounds();this.layer.addFeatures([this.line,this.point],{silent:!0})},destroyFeature:function(a){OpenLayers.Handler.Point.prototype.destroyFeature.call(this,a);this.line=null},destroyPersistedFeature:function(){var a=this.layer;a&&2this.nbPoints&&this.points.pop()},end:function(a){for(var b,c=(new Date).getTime(),d=0,e=this.points.length,f;dthis.delay)break;b=f}if(b&&(d=(new Date).getTime()-b.tick,c=Math.sqrt(Math.pow(a.x-b.xy.x,2)+Math.pow(a.y-b.xy.y,2)),d=c/d,!(0==d||d=-this.deceleration*a+c&&(OpenLayers.Animation.stop(this.timerId),this.timerId=null,n=!0);a=m-g;p=l-h;g=m;h=l;b(a,p,n)}},this))},CLASS_NAME:"OpenLayers.Kinetic"});OpenLayers.Format.WPSExecute=OpenLayers.Class(OpenLayers.Format.XML,OpenLayers.Format.Filter.v1_1_0,{namespaces:{ows:"http://www.opengis.net/ows/1.1",gml:"http://www.opengis.net/gml",wps:"http://www.opengis.net/wps/1.0.0",wfs:"http://www.opengis.net/wfs",ogc:"http://www.opengis.net/ogc",wcs:"http://www.opengis.net/wcs",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},regExes:{trimSpace:/^\s*|\s*$/g,removeSpace:/\s*/g,splitSpace:/\s+/,trimComma:/\s*,\s*/g},VERSION:"1.0.0", + schemaLocation:"http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsAll.xsd",schemaLocationAttr:function(a){},write:function(a){var b;window.ActiveXObject?this.xmldom=b=new ActiveXObject("Microsoft.XMLDOM"):b=document.implementation.createDocument("","",null);a=this.writeNode("wps:Execute",a,b);this.setAttributeNS(a,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[a])},read:function(a){"string"==typeof a&&(a= + OpenLayers.Format.XML.prototype.read.apply(this,[a]));a&&9==a.nodeType&&(a=a.documentElement);var b={};this.readNode(a,b);return b},writers:{wps:{Execute:function(a){var b=this.createElementNSPlus("wps:Execute",{attributes:{version:this.VERSION,service:"WPS"}});this.writeNode("ows:Identifier",a.identifier,b);this.writeNode("wps:DataInputs",a.dataInputs,b);this.writeNode("wps:ResponseForm",a.responseForm,b);return b},ResponseForm:function(a){var b=this.createElementNSPlus("wps:ResponseForm",{});a.rawDataOutput&& + this.writeNode("wps:RawDataOutput",a.rawDataOutput,b);a.responseDocument&&this.writeNode("wps:ResponseDocument",a.responseDocument,b);return b},ResponseDocument:function(a){var b=this.createElementNSPlus("wps:ResponseDocument",{attributes:{storeExecuteResponse:a.storeExecuteResponse,lineage:a.lineage,status:a.status}});if(a.outputs)for(var c=0,d=a.outputs.length;c';k&&(l+='');l+=g;k&&(l+="");l+="";l+='
';l+=h;l+="
";e.popupContentHTML=l}f=new OpenLayers.Feature(this,f,e);this.features.push(f); + e=f.createMarker();e.events.register("click",f,this.markerClick);this.addMarker(e)}}this.events.triggerEvent("loadend")},markerClick:function(a){var b=this==this.layer.selectedFeature;this.layer.selectedFeature=b?null:this;for(var c=0,d=this.layer.map.popups.length;c1/3&&e<2/3?d="c":e>=2/3&&(d="r");f<=1/3?d+="b":f>1/3&&f<2/3?d+="m":f>=2/3&&(d+="t");c.labelAlign=d;OpenLayers.Util.applyDefaults(b,c)},AnchorPoint:function(a,b){this.readChildNodes(a,b)},AnchorPointX:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelAnchorPointX=c)},AnchorPointY:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelAnchorPointY=c)},Displacement:function(a, + b){this.readChildNodes(a,b)},DisplacementX:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelXOffset=c)},DisplacementY:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelYOffset=c)},LinePlacement:function(a,b){this.readChildNodes(a,b)},PerpendicularOffset:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.labelPerpendicularOffset=c)},Label:function(a,b){var c=this.readers.ogc._expression.call(this,a);c&&(b.label=c)},Font:function(a,b){this.readChildNodes(a, + b)},Halo:function(a,b){var c={};this.readChildNodes(a,c);b.haloRadius=c.haloRadius;b.haloColor=c.fillColor;b.haloOpacity=c.fillOpacity},Radius:function(a,b){var c=this.readers.ogc._expression.call(this,a);null!=c&&(b.haloRadius=c)},RasterSymbolizer:function(a,b){var c={};this.readChildNodes(a,c);this.multipleSymbolizers?(c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Raster(c))):b.symbolizer.Raster=OpenLayers.Util.applyDefaults(c,b.symbolizer.Raster)},Geometry:function(a, + b){b.geometry={};this.readChildNodes(a,b.geometry)},ColorMap:function(a,b){b.colorMap=[];this.readChildNodes(a,b.colorMap)},ColorMapEntry:function(a,b){var c=a.getAttribute("quantity"),d=a.getAttribute("opacity");b.push({color:a.getAttribute("color"),quantity:null!==c?parseFloat(c):void 0,label:a.getAttribute("label")||void 0,opacity:null!==d?parseFloat(d):void 0})},LineSymbolizer:function(a,b){var c={};this.readChildNodes(a,c);this.multipleSymbolizers?(c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Line(c))): + b.symbolizer.Line=OpenLayers.Util.applyDefaults(c,b.symbolizer.Line)},PolygonSymbolizer:function(a,b){var c={fill:!1,stroke:!1};this.multipleSymbolizers||(c=b.symbolizer.Polygon||c);this.readChildNodes(a,c);this.multipleSymbolizers?(c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Polygon(c))):b.symbolizer.Polygon=c},PointSymbolizer:function(a,b){var c={fill:!1,stroke:!1,graphic:!1};this.multipleSymbolizers||(c=b.symbolizer.Point||c);this.readChildNodes(a,c);this.multipleSymbolizers? + (c.zIndex=this.featureTypeCounter,b.symbolizers.push(new OpenLayers.Symbolizer.Point(c))):b.symbolizer.Point=c},Stroke:function(a,b){b.stroke=!0;this.readChildNodes(a,b)},Fill:function(a,b){b.fill=!0;this.readChildNodes(a,b)},CssParameter:function(a,b){var c=a.getAttribute("name"),d=this.cssMap[c];b.label&&("fill"===c?d="fontColor":"fill-opacity"===c&&(d="fontOpacity"));d&&(c=this.readers.ogc._expression.call(this,a))&&(b[d]=c)},Graphic:function(a,b){b.graphic=!0;var c={};this.readChildNodes(a,c); + for(var d="stroke strokeColor strokeWidth strokeOpacity strokeLinecap fill fillColor fillOpacity graphicName rotation graphicFormat".split(" "),e,f,g=0,h=d.length;g=-this.MAX_PIXEL&&a<=this.MAX_PIXEL&&b>=-this.MAX_PIXEL&&b<=this.MAX_PIXEL},setExtent:function(a,b){var c=OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments),d=this.getResolution(),e=-a.left/d,d=a.top/d;if(b)return this.left=e,this.top=d,this.rendererRoot.setAttributeNS(null, + "viewBox","0 0 "+this.size.w+" "+this.size.h),this.translate(this.xOffset,0),!0;(e=this.translate(e-this.left+this.xOffset,d-this.top))||this.setExtent(a,!0);return c&&e},translate:function(a,b){if(this.inValidRange(a,b,!0)){var c="";if(a||b)c="translate("+a+","+b+")";this.root.setAttributeNS(null,"transform",c);this.translationParameters={x:a,y:b};return!0}return!1},setSize:function(a){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);this.rendererRoot.setAttributeNS(null,"width",this.size.w); + this.rendererRoot.setAttributeNS(null,"height",this.size.h)},getNodeType:function(a,b){var c=null;switch(a.CLASS_NAME){case "OpenLayers.Geometry.Point":c=b.externalGraphic?"image":this.isComplexSymbol(b.graphicName)?"svg":"circle";break;case "OpenLayers.Geometry.Rectangle":c="rect";break;case "OpenLayers.Geometry.LineString":c="polyline";break;case "OpenLayers.Geometry.LinearRing":c="polygon";break;case "OpenLayers.Geometry.Polygon":case "OpenLayers.Geometry.Curve":c="path"}return c},setStyle:function(a, + b,c){b=b||a._style;c=c||a._options;var d=b.title||b.graphicTitle;if(d){a.setAttributeNS(null,"title",d);var e=a.getElementsByTagName("title");0k;)f.removeChild(f.lastChild);for(var l=0;ld)k=(c-g)/(h-f),h=0>h?-d:d,c=g+(h-f)*k;if(c<-e||c>e)k=(h-f)/(c-g),c=0>c?-e:e,h=f+(c-g)*k;return h+","+c},getShortString:function(a){var b=this.getResolution(),c=(a.x-this.featureDx)/b+this.left;a=this.top-a.y/b;return this.inValidRange(c, + a)?c+","+a:!1},getPosition:function(a){return{x:parseFloat(a.getAttributeNS(null,"cx")),y:parseFloat(a.getAttributeNS(null,"cy"))}},importSymbol:function(a){this.defs||(this.defs=this.createDefs());var b=this.container.id+"-"+a,c=document.getElementById(b);if(null!=c)return c;var d=OpenLayers.Renderer.symbol[a];if(!d)throw Error(a+" is not a valid symbol name");a=this.nodeFactory(b,"symbol");var e=this.nodeFactory(null,"polygon");a.appendChild(e);for(var c=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE, + 0,0),f=[],g,h,k=0;k"+this.contentDiv.innerHTML+"",b=this.map?this.map.div:document.body,c=OpenLayers.Util.getRenderedDimensions(a, + null,{displayClass:this.displayClass,containerElement:b}),d=this.getSafeContentSize(c),e=null;d.equals(c)?e=c:(c={w:d.wa.w-this.map.paddingForPopups.right&&(c.x=a.w-this.map.paddingForPopups.right-this.size.w); + b.ya.h-this.map.paddingForPopups.bottom&&(c.y=a.h-this.map.paddingForPopups.bottom-this.size.h);this.map.pan(b.x-c.x,b.y-c.y)},registerEvents:function(){this.events=new OpenLayers.Events(this,this.div,null,!0);this.events.on({mousedown:this.onmousedown,mousemove:this.onmousemove,mouseup:this.onmouseup,click:this.onclick,mouseout:this.onmouseout,dblclick:this.ondblclick,touchstart:function(a){OpenLayers.Event.stop(a,!0)}, + scope:this})},onmousedown:function(a){this.mousedown=!0;OpenLayers.Event.stop(a,!0)},onmousemove:function(a){this.mousedown&&OpenLayers.Event.stop(a,!0)},onmouseup:function(a){this.mousedown&&(this.mousedown=!1,OpenLayers.Event.stop(a,!0))},onclick:function(a){OpenLayers.Event.stop(a,!0)},onmouseout:function(a){this.mousedown=!1},ondblclick:function(a){OpenLayers.Event.stop(a,!0)},CLASS_NAME:"OpenLayers.Popup"});OpenLayers.Popup.WIDTH=200;OpenLayers.Popup.HEIGHT=200;OpenLayers.Popup.COLOR="white"; +OpenLayers.Popup.OPACITY=1;OpenLayers.Popup.BORDER="0px";OpenLayers.Control.ScaleLine=OpenLayers.Class(OpenLayers.Control,{maxWidth:100,topOutUnits:"km",topInUnits:"m",bottomOutUnits:"mi",bottomInUnits:"ft",eTop:null,eBottom:null,geodesic:!1,draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.eTop||(this.eTop=document.createElement("div"),this.eTop.className=this.displayClass+"Top",this.div.appendChild(this.eTop),this.eTop.style.visibility=""==this.topOutUnits||""==this.topInUnits?"hidden":"visible",this.eBottom=document.createElement("div"), + this.eBottom.className=this.displayClass+"Bottom",this.div.appendChild(this.eBottom),this.eBottom.style.visibility=""==this.bottomOutUnits||""==this.bottomInUnits?"hidden":"visible");this.map.events.register("moveend",this,this.update);this.update();return this.div},getBarLen:function(a){var b=parseInt(Math.log(a)/Math.log(10)),b=Math.pow(10,b);a=parseInt(a/b);return(5Math.abs(n)?1:l/n,h=(1E-5>Math.abs(m)?1:k/m)/l):(m=Math.sqrt(m*m+n*n),l=Math.sqrt(k*k+l*l)/m);a._moving=!0;a.box.geometry.rotate(-a.rotation,f);delete a._moving;a.box.geometry.resize(l,f,h);a.box.geometry.rotate(a.rotation,f);a.transformFeature({scale:l, + ratio:h});a.irregular&&!a._setfeature&&(k=f.clone(),k.x+=1E-5>Math.abs(d-f.x)?0:this.x-d,k.y+=1E-5>Math.abs(e-f.y)?0:this.y-e,a.box.geometry.move(this.x-d,this.y-e),a.transformFeature({center:k}))}},f=function(b,c){var d=this.x,e=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,b,c);if(!a._moving){var f=a.dragControl.handlers.drag.evt,f=f&&f.shiftKey?45:1,g=a.center,h=this.x-g.x,k=this.y-g.y;this.x=d;this.y=e;d=Math.atan2(k-c,h-b);d=Math.atan2(k,h)-d;d*=180/Math.PI;a._angle=(a._angle+d)% + 360;d=a.rotation%f;if(Math.abs(a._angle)>=f||0!==d)d=Math.round(a._angle/f)*f-d,a._angle=0,a.box.geometry.rotate(d,g),a.transformFeature({rotation:d})}},g=Array(8),h=Array(4),k,l,m,n="sw s se e ne n nw w".split(" "),p=0;8>p;++p)k=this.box.geometry.components[p],l=new OpenLayers.Feature.Vector(k.clone(),{role:n[p]+"-resize"},"string"==typeof this.renderIntent?null:this.renderIntent),0==p%2&&(m=new OpenLayers.Feature.Vector(k.clone(),{role:n[p]+"-rotate"},"string"==typeof this.rotationHandleSymbolizer? + null:this.rotationHandleSymbolizer),m.geometry.move=f,k._rotationHandle=m,h[p/2]=m),k.move=b,k.resize=c,k.rotate=d,l.geometry.move=e,k._handle=l,g[p]=l;this.rotationHandles=h;this.handles=g},createControl:function(){var a=this;this.dragControl=new OpenLayers.Control.DragFeature(this.layer,{documentDrag:!0,moveFeature:function(b){this.feature===a.feature&&(this.feature=a.box);OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,arguments)},onDrag:function(b,c){b===a.box&&a.transformFeature({center:a.center})}, + onStart:function(b,c){var d=!a.geometryTypes||-1!==OpenLayers.Util.indexOf(a.geometryTypes,b.geometry.CLASS_NAME),e=OpenLayers.Util.indexOf(a.handles,b),e=e+OpenLayers.Util.indexOf(a.rotationHandles,b);b!==a.feature&&(b!==a.box&&-2==e&&d)&&a.setFeature(b)},onComplete:function(b,c){a.events.triggerEvent("transformcomplete",{feature:a.feature})}})},drawHandles:function(){for(var a=this.layer,b=0;8>b;++b)this.rotate&&0===b%2&&a.drawFeature(this.rotationHandles[b/2],this.rotationHandleSymbolizer),a.drawFeature(this.handles[b], + this.renderIntent)},transformFeature:function(a){if(!this._setfeature){this.scale*=a.scale||1;this.ratio*=a.ratio||1;var b=this.rotation;this.rotation=(this.rotation+(a.rotation||0))%360;if(!1!==this.events.triggerEvent("beforetransform",a)){var c=this.feature,d=c.geometry,e=this.center;d.rotate(-b,e);a.scale||a.ratio?d.resize(a.scale,e,a.ratio):a.center&&c.move(a.center.getBounds().getCenterLonLat());d.rotate(this.rotation,e);this.layer.drawFeature(c);c.toState(OpenLayers.State.UPDATE);this.events.triggerEvent("transform", + a)}}this.layer.drawFeature(this.box,this.renderIntent);this.drawHandles()},destroy:function(){for(var a,b=0;8>b;++b)a=this.box.geometry.components[b],a._handle.destroy(),a._handle=null,a._rotationHandle&&a._rotationHandle.destroy(),a._rotationHandle=null;this.rotationHandles=this.rotationHandleSymbolizer=this.handles=this.feature=this.center=null;this.box.destroy();this.layer=this.box=null;this.dragControl.destroy();this.dragControl=null;OpenLayers.Control.prototype.destroy.apply(this,arguments)}, + CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:"olHandlerBoxZoomBox",boxOffsets:null,initialize:function(a,b,c){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.dragHandler=new OpenLayers.Handler.Drag(this,{down:this.startBox,move:this.moveBox,out:this.removeBox,up:this.endBox},{keyMask:this.keyMask})},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);this.dragHandler&&(this.dragHandler.destroy(),this.dragHandler= + null)},setMap:function(a){OpenLayers.Handler.prototype.setMap.apply(this,arguments);this.dragHandler&&this.dragHandler.setMap(a)},startBox:function(a){this.callback("start",[]);this.zoomBox=OpenLayers.Util.createDiv("zoomBox",{x:-9999,y:-9999});this.zoomBox.className=this.boxDivClassName;this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE.Popup-1;this.map.viewPortDiv.appendChild(this.zoomBox);OpenLayers.Element.addClass(this.map.viewPortDiv,"olDrawBox")},moveBox:function(a){var b=this.dragHandler.start.x, + c=this.dragHandler.start.y,d=Math.abs(b-a.x),e=Math.abs(c-a.y),f=this.getBoxOffsets();this.zoomBox.style.width=d+f.width+1+"px";this.zoomBox.style.height=e+f.height+1+"px";this.zoomBox.style.left=(a.x=this.resFactor||a<=1/this.resFactor);return a},calculateBounds:function(a){a||(a=this.getMapBounds());var b=a.getCenterLonLat(),c=a.getWidth()*this.ratio;a=a.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(b.lon-c/2,b.lat-a/2,b.lon+c/2,b.lat+a/2)},triggerRead:function(a){!this.response||a&&!0===a.noAbort|| +(this.layer.protocol.abort(this.response),this.layer.events.triggerEvent("loadend"));var b={filter:this.createFilter()};this.layer.events.triggerEvent("loadstart",b);this.response=this.layer.protocol.read(OpenLayers.Util.applyDefaults({filter:b.filter,callback:this.merge,scope:this},a))},createFilter:function(){var a=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});this.layer.filter&&(a=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND, + filters:[this.layer.filter,a]}));return a},merge:function(a){this.layer.destroyFeatures();if(a.success()){var b=a.features;if(b&&0 + + Copyright 2005 Sabre Airline Solutions + + 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. + */ +OpenLayers.Marker.Box=OpenLayers.Class(OpenLayers.Marker,{bounds:null,div:null,initialize:function(a,b,c){this.bounds=a;this.div=OpenLayers.Util.createDiv();this.div.style.overflow="hidden";this.events=new OpenLayers.Events(this,this.div);this.setBorder(b,c)},destroy:function(){this.div=this.bounds=null;OpenLayers.Marker.prototype.destroy.apply(this,arguments)},setBorder:function(a,b){a||(a="red");b||(b=2);this.div.style.border=b+"px solid "+a},draw:function(a,b){OpenLayers.Util.modifyDOMElement(this.div, + null,a,b);return this.div},onScreen:function(){var a=!1;this.map&&(a=this.map.getExtent().containsBounds(this.bounds,!0,!0));return a},display:function(a){this.div.style.display=a?"":"none"},CLASS_NAME:"OpenLayers.Marker.Box"});OpenLayers.Format.Text=OpenLayers.Class(OpenLayers.Format,{defaultStyle:null,extractStyles:!0,initialize:function(a){a=a||{};!1!==a.extractStyles&&(a.defaultStyle={externalGraphic:OpenLayers.Util.getImageLocation("marker.png"),graphicWidth:21,graphicHeight:25,graphicXOffset:-10.5,graphicYOffset:-12.5});OpenLayers.Format.prototype.initialize.apply(this,[a])},read:function(a){a=a.split("\n");for(var b,c=[],d=0;d"+e.attributes.title+"

"+e.attributes.description+"

");d.overflow=e.attributes.overflow||"auto";d=new OpenLayers.Feature(this,f,d);this.features.push(d);f=d.createMarker();null!=e.attributes.title&&null!=e.attributes.description&&f.events.register("click",d,this.markerClick);this.addMarker(f)}this.events.triggerEvent("loadend")},markerClick:function(a){var b=this==this.layer.selectedFeature;this.layer.selectedFeature= + b?null:this;for(var c=0,d=this.layer.map.popups.length;c=a?Math.round(a/1E3)+"K":95E4<=a?Math.round(a/1E6)+"M":Math.round(a),this.element.innerHTML=OpenLayers.i18n("Scale = 1 : ${scaleDenom}",{scaleDenom:a}))},CLASS_NAME:"OpenLayers.Control.Scale"});OpenLayers.Layer.MapGuide=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:!0,useHttpTile:!1,singleTile:!1,useOverlay:!1,useAsyncOverlay:!0,TILE_PARAMS:{operation:"GETTILEIMAGE",version:"1.2.0"},SINGLE_TILE_PARAMS:{operation:"GETMAPIMAGE",format:"PNG",locale:"en",clip:"1",version:"1.0.0"},OVERLAY_PARAMS:{operation:"GETDYNAMICMAPOVERLAYIMAGE",format:"PNG",locale:"en",clip:"1",version:"2.0.0"},FOLDER_PARAMS:{tileColumnsPerFolder:30,tileRowsPerFolder:30,format:"png",querystring:null},defaultSize:new OpenLayers.Size(300, + 300),tileOriginCorner:"tl",initialize:function(a,b,c,d){OpenLayers.Layer.Grid.prototype.initialize.apply(this,arguments);if(null==d||null==d.isBaseLayer)this.isBaseLayer="true"!=this.transparent&&!0!=this.transparent;d&&null!=d.useOverlay&&(this.useOverlay=d.useOverlay);this.singleTile?this.useOverlay?(OpenLayers.Util.applyDefaults(this.params,this.OVERLAY_PARAMS),this.useAsyncOverlay||(this.params.version="1.0.0")):OpenLayers.Util.applyDefaults(this.params,this.SINGLE_TILE_PARAMS):(this.useHttpTile? + OpenLayers.Util.applyDefaults(this.params,this.FOLDER_PARAMS):OpenLayers.Util.applyDefaults(this.params,this.TILE_PARAMS),this.setTileSize(this.defaultSize))},clone:function(a){null==a&&(a=new OpenLayers.Layer.MapGuide(this.name,this.url,this.params,this.getOptions()));return a=OpenLayers.Layer.Grid.prototype.clone.apply(this,[a])},getURL:function(a){var b;b=a.getCenterLonLat();var c=this.map.getSize();this.singleTile?(a={setdisplaydpi:OpenLayers.DOTS_PER_INCH,setdisplayheight:c.h*this.ratio,setdisplaywidth:c.w* +this.ratio,setviewcenterx:b.lon,setviewcentery:b.lat,setviewscale:this.map.getScale()},this.useOverlay&&!this.useAsyncOverlay&&(b={},b=OpenLayers.Util.extend(b,a),b.operation="GETVISIBLEMAPEXTENT",b.version="1.0.0",b.session=this.params.session,b.mapName=this.params.mapName,b.format="text/xml",b=this.getFullRequestString(b),OpenLayers.Request.GET({url:b,async:!1})),b=this.getFullRequestString(a)):(c=this.map.getResolution(),b=Math.floor((a.left-this.maxExtent.left)/c),b=Math.round(b/this.tileSize.w), + a=Math.floor((this.maxExtent.top-a.top)/c),a=Math.round(a/this.tileSize.h),b=this.useHttpTile?this.getImageFilePath({tilecol:b,tilerow:a,scaleindex:this.resolutions.length-this.map.zoom-1}):this.getFullRequestString({tilecol:b,tilerow:a,scaleindex:this.resolutions.length-this.map.zoom-1}));return b},getFullRequestString:function(a,b){var c=null==b?this.url:b;"object"==typeof c&&(c=c[Math.floor(Math.random()*c.length)]);var d=c,e=OpenLayers.Util.extend({},this.params),e=OpenLayers.Util.extend(e,a), + f=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(c)),g;for(g in e)g.toUpperCase()in f&&delete e[g];e=OpenLayers.Util.getParameterString(e);e=e.replace(/,/g,"+");""!=e&&(f=c.charAt(c.length-1),d="&"==f||"?"==f?d+e:-1==c.indexOf("?")?d+("?"+e):d+("&"+e));return d},getImageFilePath:function(a,b){var c=null==b?this.url:b;"object"==typeof c&&(c=c[Math.floor(Math.random()*c.length)]);var d="",e="";0>a.tilerow&&(d="-");d=0==a.tilerow?d+"0":d+Math.floor(Math.abs(a.tilerow/this.params.tileRowsPerFolder))* +this.params.tileRowsPerFolder;0>a.tilecol&&(e="-");e=0==a.tilecol?e+"0":e+Math.floor(Math.abs(a.tilecol/this.params.tileColumnsPerFolder))*this.params.tileColumnsPerFolder;d="/S"+Math.floor(a.scaleindex)+"/"+this.params.basemaplayergroupname+"/R"+d+"/C"+e+"/"+a.tilerow%this.params.tileRowsPerFolder+"_"+a.tilecol%this.params.tileColumnsPerFolder+"."+this.params.format;this.params.querystring&&(d+="?"+this.params.querystring);return c+d},CLASS_NAME:"OpenLayers.Layer.MapGuide"});OpenLayers.Control.Measure=OpenLayers.Class(OpenLayers.Control,{callbacks:null,displaySystem:"metric",geodesic:!1,displaySystemUnits:{geographic:["dd"],english:["mi","ft","in"],metric:["km","m"]},partialDelay:300,delayedTrigger:null,persist:!1,immediate:!1,initialize:function(a,b){OpenLayers.Control.prototype.initialize.apply(this,[b]);var c={done:this.measureComplete,point:this.measurePartial};this.immediate&&(c.modify=this.measureImmediate);this.callbacks=OpenLayers.Util.extend(c,this.callbacks); + this.handlerOptions=OpenLayers.Util.extend({persist:this.persist},this.handlerOptions);this.handler=new a(this,this.callbacks,this.handlerOptions)},deactivate:function(){this.cancelDelay();return OpenLayers.Control.prototype.deactivate.apply(this,arguments)},cancel:function(){this.cancelDelay();this.handler.cancel()},setImmediate:function(a){(this.immediate=a)?this.callbacks.modify=this.measureImmediate:delete this.callbacks.modify},updateHandler:function(a,b){var c=this.active;c&&this.deactivate(); + this.handler=new a(this,this.callbacks,b);c&&this.activate()},measureComplete:function(a){this.cancelDelay();this.measure(a,"measure")},measurePartial:function(a,b){this.cancelDelay();b=b.clone();this.handler.freehandMode(this.handler.evt)?this.measure(b,"measurepartial"):this.delayedTrigger=window.setTimeout(OpenLayers.Function.bind(function(){this.delayedTrigger=null;this.measure(b,"measurepartial")},this),this.partialDelay)},measureImmediate:function(a,b,c){c&&!this.handler.freehandMode(this.handler.evt)&& +(this.cancelDelay(),this.measure(b.geometry,"measurepartial"))},cancelDelay:function(){null!==this.delayedTrigger&&(window.clearTimeout(this.delayedTrigger),this.delayedTrigger=null)},measure:function(a,b){var c,d;-1k?0:k)+"px";d.div.style.height=(0>l?0:l)+"px";d.div.style.left=null!=e?e+"px":"";d.div.style.bottom=null!=f?f+"px":"";d.div.style.right=null!=g?g+"px":"";d.div.style.top=null!=h?h+"px":"";d.image.style.left=c.position.x+"px";d.image.style.top=c.position.y+"px"}this.contentDiv.style.left=this.padding.left+"px";this.contentDiv.style.top=this.padding.top+"px"}},CLASS_NAME:"OpenLayers.Popup.Framed"});OpenLayers.Popup.FramedCloud=OpenLayers.Class(OpenLayers.Popup.Framed,{contentDisplayClass:"olFramedCloudPopupContent",autoSize:!0,panMapIfOutOfView:!0,imageSize:new OpenLayers.Size(1276,736),isAlphaImage:!1,fixedRelativePosition:!1,positionBlocks:{tl:{offset:new OpenLayers.Pixel(44,0),padding:new OpenLayers.Bounds(8,40,8,9),blocks:[{size:new OpenLayers.Size("auto","auto"),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null, + 50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size("auto",19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,18),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-632)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(0,-688)}]},tr:{offset:new OpenLayers.Pixel(-45,0),padding:new OpenLayers.Bounds(8,40,8,9),blocks:[{size:new OpenLayers.Size("auto", + "auto"),anchor:new OpenLayers.Bounds(0,51,22,0),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null,50,0,0),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size("auto",19),anchor:new OpenLayers.Bounds(0,32,22,null),position:new OpenLayers.Pixel(0,-631)},{size:new OpenLayers.Size(22,19),anchor:new OpenLayers.Bounds(null,32,0,null),position:new OpenLayers.Pixel(-1238,-631)},{size:new OpenLayers.Size(81,35),anchor:new OpenLayers.Bounds(0, + 0,null,null),position:new OpenLayers.Pixel(-215,-687)}]},bl:{offset:new OpenLayers.Pixel(45,0),padding:new OpenLayers.Bounds(8,9,8,40),blocks:[{size:new OpenLayers.Size("auto","auto"),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238,0)},{size:new OpenLayers.Size("auto",21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22, + 21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(null,null,0,0),position:new OpenLayers.Pixel(-101,-674)}]},br:{offset:new OpenLayers.Pixel(-44,0),padding:new OpenLayers.Bounds(8,9,8,40),blocks:[{size:new OpenLayers.Size("auto","auto"),anchor:new OpenLayers.Bounds(0,21,22,32),position:new OpenLayers.Pixel(0,0)},{size:new OpenLayers.Size(22,"auto"),anchor:new OpenLayers.Bounds(null,21,0,32),position:new OpenLayers.Pixel(-1238, + 0)},{size:new OpenLayers.Size("auto",21),anchor:new OpenLayers.Bounds(0,0,22,null),position:new OpenLayers.Pixel(0,-629)},{size:new OpenLayers.Size(22,21),anchor:new OpenLayers.Bounds(null,0,0,null),position:new OpenLayers.Pixel(-1238,-629)},{size:new OpenLayers.Size(81,33),anchor:new OpenLayers.Bounds(0,null,null,0),position:new OpenLayers.Pixel(-311,-674)}]}},minSize:new OpenLayers.Size(105,10),maxSize:new OpenLayers.Size(1200,660),initialize:function(a,b,c,d,e,f,g){this.imageSrc=OpenLayers.Util.getImageLocation("cloud-popup-relative.png"); + OpenLayers.Popup.Framed.prototype.initialize.apply(this,arguments);this.contentDiv.className=this.contentDisplayClass},CLASS_NAME:"OpenLayers.Popup.FramedCloud"});OpenLayers.Tile.Image.IFrame={useIFrame:null,blankImageUrl:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAQAIBRAA7",draw:function(){if(OpenLayers.Tile.Image.prototype.shouldDraw.call(this)){var a=this.layer.getURL(this.bounds),b=this.useIFrame;this.useIFrame=null!==this.maxGetUrlLength&&!this.layer.async&&a.length>this.maxGetUrlLength;a=b&&!this.useIFrame;b=!b&&this.useIFrame;if(a||b)this.imgDiv&&this.imgDiv.parentNode===this.frame&&this.frame.removeChild(this.imgDiv),this.imgDiv= + null,a&&this.frame.removeChild(this.frame.firstChild)}return OpenLayers.Tile.Image.prototype.draw.apply(this,arguments)},getImage:function(){if(!0===this.useIFrame){if(!this.frame.childNodes.length){var a=document.createElement("div"),b=a.style;b.position="absolute";b.width="100%";b.height="100%";b.zIndex=1;b.backgroundImage="url("+this.blankImageUrl+")";this.frame.appendChild(a)}a=this.id+"_iFrame";9>parseFloat(navigator.appVersion.split("MSIE")[1])?(b=document.createElement('